我想测试一种将标头添加到GET请求中的方法,以便与公共API建立连接。 我的带有业务逻辑的服务如下:
@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看起来像:
@PropertySource("classpath:nutritionix.properties")
@Configuration
@Getter
@NoArgsConstructor
public class NutritionixHeader {
@Value("${nutritionix-app-id}")
private String NutritionixAppId;
@Value("${nutritionix-app-key}")
private String NutritionixAppKey;
}
我的测试类如下:
@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();
}
该行出现问题:
HttpHeaders headers = productsResponse.getHeaders();
带有NullPointerException。
我所需要做的就是测试我的方法是否已正确将标头添加到GET查询中。
我有点困惑,因为似乎我对所有东西都进行了嘲笑,但仍然收到空指针。也许我的NPE与我的RestTemplate对象没有模拟的事实有关。如果是真的,我将不胜感激为您提供有关如何解决此问题的建议。
答案 0 :(得分:2)
您需要使用ArgumentCaptor捕获HttpEntity,然后获取标头。看一下代码:
@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();
}