I want to test a method which will add headers to my GET request in order to establish a connection with public API. My service with business logic looks like:
@Service
public class RestTemplateFacade {
private NutritionixHeader nutritionHeaderParam;
private RestTemplate restTemplate;
public RestTemplateFacade(
NutritionixHeader nutritionHeaderParam,
RestTemplate restTemplate) {
this.nutritionHeaderParam = nutritionHeaderParam;
this.restTemplate = restTemplate;
}
public ResponseEntity<Products> addHeaderToRequest(String queryParam) {
HttpHeaders headers = new HttpHeaders();
headers.set("x-app-id", nutritionHeaderParam.getNutritionixAppId());
headers.set("x-app-key", nutritionHeaderParam.getNutritionixAppKey());
UriComponentsBuilder uriBuilder = UriComponentsBuilder
.fromHttpUrl("https://trackapi.nutritionix.com/v2/search/instant")
.queryParam("query", queryParam);
HttpEntity httpEntity = new HttpEntity(headers);
return
restTemplate
.exchange(
uriBuilder.toUriString(),
HttpMethod.GET,
httpEntity,
Products.class);
}
}
NutritionixHeader.class looks like:
@PropertySource("classpath:nutritionix.properties")
@Configuration
@Getter
@NoArgsConstructor
public class NutritionixHeader {
@Value("${nutritionix-app-id}")
private String NutritionixAppId;
@Value("${nutritionix-app-key}")
private String NutritionixAppKey;
}
My test class looks like:
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class RestTemplateFacadeTest {
@Mock
private NutritionixHeader nutritionixHeader;
@Mock
private RestTemplate restTemplate;
@InjectMocks
private RestTemplateFacade restTemplateFacade;
@Mock
private UriComponentsBuilder uriComponentsBuilder;
@BeforeEach
void setUp() {
restTemplateFacade = new RestTemplateFacade(nutritionixHeader, restTemplate);
}
@Test
void addHeaderToRequest() {
//given
var query = "query";
given(nutritionixHeader.getNutritionixAppId()).willReturn("x-app-id");
given(nutritionixHeader.getNutritionixAppKey()).willReturn("x-app-key");
//when
ResponseEntity<Products> productsResponse = restTemplateFacade.addHeaderToRequest(query);
HttpHeaders headers = productsResponse.getHeaders();
//then
assertEquals("x-app-id",
headers.entrySet()
.stream()
.filter(entry -> entry.getKey().equals("x-app-id"))
.map(Entry::getValue)
.flatMap(Collection::stream)
.findFirst()
.orElse(""));
then(nutritionixHeader).should(times(1)).getNutritionixAppId();
}
Problem occurs in the line:
HttpHeaders headers = productsResponse.getHeaders();
with NullPointerException.
All I need is the ability to test if my method has correctly added headers to my GET query.
I am a little bit confused because it seems that I mocked everything properly but still receiving null pointer. Maybe my NPE is related to the fact there is no mock for my RestTemplate object. If it's true I will be grateful for suggestions on how to fix this problem.
You need use ArgumentCaptor to catch HttpEntity and then get the headers. Have a look at the code:
@Test
void addHeaderToRequest() {
//given
var query = "query";
given(nutritionixHeader.getNutritionixAppId()).willReturn("x-app-id");
given(nutritionixHeader.getNutritionixAppKey()).willReturn("x-app-key");
//when
restTemplateFacade.addHeaderToRequest(query);
//then
ArgumentCaptor<HttpEntity> httpEntityCapture = ArgumentCaptor.forClass(HttpEntity.class);
String url = "https://trackapi.nutritionix.com/v2/search/instant?query=query";
verify(restTemplate).exchange(eq(url), eq(HttpMethod.GET), httpEntityCapture.capture(), eq(Products.class));
HttpHeaders headers = httpEntityCapture.getValue().getHeaders();
assertEquals("x-app-id",
headers.entrySet()
.stream()
.filter(entry -> entry.getKey().equals("x-app-id"))
.map(Map.Entry::getValue)
.flatMap(Collection::stream)
.findFirst()
.orElse(""));
then(nutritionixHeader).should(times(1)).getNutritionixAppId();
}