Quiero poner a prueba un método que añadir cabeceras a mi solicitud GET con el fin de establecer una conexión con la API pública. Mi servicio con la lógica de negocio se ve así:
@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);
}
}
miradas NutritionixHeader.class como:
@PropertySource("classpath:nutritionix.properties")
@Configuration
@Getter
@NoArgsConstructor
public class NutritionixHeader {
@Value("${nutritionix-app-id}")
private String NutritionixAppId;
@Value("${nutritionix-app-key}")
private String NutritionixAppKey;
}
Mi apariencia de clase prueba como:
@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();
}
Problema ocurre en la línea:
HttpHeaders headers = productsResponse.getHeaders();
con NullPointerException.
Todo lo que necesito es la capacidad de probar si mi método ha añadido correctamente las tuberías principales a mi consulta GET.
Estoy un poco confundido porque parece que me burlé todo correctamente, pero sigue recibiendo puntero nulo. Tal vez mi NPE está relacionado con el hecho de que no hay maqueta para mi objeto RestTemplate. Si bien es cierto estaré agradecido por las sugerencias sobre cómo solucionar este problema.
Usted necesita el uso ArgumentCaptor para atrapar HttpEntity y luego obtener las cabeceras. Echar un vistazo al código:
@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();
}