code: package com.taxonic.carml.engine;
  
  import static org.hamcrest.core.Is.is;
  import static org.hamcrest.MatcherAssert.assertThat;
  import static org.mockito.Mockito.when;
  
  import java.util.List;
  import java.util.Optional;
  import java.util.function.Function;
  
  import org.junit.Rule;
  import org.junit.Test;
  import org.mockito.Mock;
  import org.mockito.junit.MockitoJUnit;
  import org.mockito.junit.MockitoRule;
  
  import com.taxonic.carml.engine.template.Template;
  import com.taxonic.carml.engine.template.TemplateParser;
  
  public class GetTemplateValueTest {
  
  	@Mock
  	Function<String, String> transformValue;
  
  	@Mock
  	Function<Object, String> createNaturalRdfLexicalForm;
  
  	@Mock
  	EvaluateExpression evaluateExpression;
  
  	@Rule
  	public MockitoRule mockitoRule = MockitoJUnit.rule();
  
  	@Test
  	public void getTemplateValue_givenValidInputAndFindingValue_performsAsExpected() {
  		when(evaluateExpression.apply("xyz")).thenReturn(Optional.of("evaluated"));
  		when(createNaturalRdfLexicalForm.apply("evaluated")).thenReturn("natural");
  		when(transformValue.apply("natural")).thenReturn("transformed");
  
  		Template template = TemplateParser.build().parse("abc{xyz}");
  		GetTemplateValue getTemplateValue =
  			new GetTemplateValue(
  				template,
  				template.getExpressions(),
  				transformValue,
  				createNaturalRdfLexicalForm
  			);
  		Optional<Object> templateValue = getTemplateValue.apply(evaluateExpression);
  		String result = unpackTemplateValue(templateValue);
  		assertThat(result, is("abctransformed"));
  	}
  
  	private String unpackTemplateValue(Optional<Object> templateValue) {
  		return templateValue.map(v -> {
  			if (v instanceof List<?>) {
  				List<?> list = (List<?>)v;
  				assertThat(list.size(), is(1));
  				return (String)(list).get(0);
  			} else {
  				throw new RuntimeException();
  			}
  		}).orElseThrow(RuntimeException::new);
  	}
  
  	@Test
  	public void getTemplateValue_givenValidInputWithMultipleExpressions_performsAsExpected() {
  		when(evaluateExpression.apply("xyz")).thenReturn(Optional.of("evaluated"));
  		when(createNaturalRdfLexicalForm.apply("evaluated")).thenReturn("natural");
  		when(transformValue.apply("natural")).thenReturn("transformed");
  
  		Template template = TemplateParser.build().parse("abc{xyz}{xyz}");
  		GetTemplateValue getTemplateValue =
  			new GetTemplateValue(
  				template,
  				template.getExpressions(),
  				transformValue,
  				createNaturalRdfLexicalForm
  			);
  		Optional<Object>templateValue = getTemplateValue.apply(evaluateExpression);
  		String result = unpackTemplateValue(templateValue);
  		assertThat(result, is("abctransformedtransformed"));
  	}
  
  	@Test
  	public void getTemplateValue_givenValidInputAndNotFindingValue_returnsNoValues() {
  		when(evaluateExpression.apply("xyz")).thenReturn(Optional.empty());
  
  		Template template = TemplateParser.build().parse("abc{xyz}");
  		GetTemplateValue getTemplateValue =
  			new GetTemplateValue(
  				template,
  				template.getExpressions(),
  				transformValue,
  				createNaturalRdfLexicalForm
  			);
  		Optional<Object> templateValue = getTemplateValue.apply(evaluateExpression);
  		assertThat(templateValue, is(Optional.empty()));
  	}
  
  }
  