我在为我的collect
方法编写单元测试时遇到了困难。具体地说,在collectEndpointCount
方法中调用getBearerToken()
之后发生的方法的Jacoco测试覆盖率没有得到识别。StepVerifier能够验证它是否已完成,但其中的值都为null。
下面是我的collect
的快速分解。它接受一个timeRange
,并使用collectEndpointCount
方法为每个端点启动2个异步操作。此方法使用extractAccessToken
和getBearerToken
检索Apigee访问令牌以验证API请求
使用构造的URL和获得的访问令牌从每个端点的外部API获取使用计数数据。然后通过processEndpointResponse
方法处理响应以提取使用计数。使用www.example.com操作合并所有2个终点的收集计数Mono.zip。
ResultsCollectorImpl.java
public ResultCollectorImpl(WebClient webClient) {
this.webClient = webClient;
}
@Override
public Mono<ResultStats> collect(String timeRange) {
Mono<Long> results1 = collectEndpointCount(timeRange, "url1");
Mono<Long> results2 = collectEndpointCount(timeRange, "url2");
return Mono.zip(results1, results2)
.map(tuple -> new ResultStats(tuple.getT1(), tuple.getT2()));
}
private Mono<String> getBearerToken() {
return webClient.post()
.uri("https://login.apigee.com/oauth/token")
.header(HttpHeaders.AUTHORIZATION, "Basic ZWRnZWNsaTplZGdlY2xpc2VjcmV0")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.bodyValue("grant_type=refresh_token&refresh_token=my_refresh_token")
.retrieve()
.bodyToMono(String.class)
.flatMap(this::extractAccessToken);
}
private Mono<String> extractAccessToken(String responseBody) {
try {
JsonNode accessTokenNode = new ObjectMapper().readTree(responseBody).get("access_token");
if (accessTokenNode != null && accessTokenNode.isTextual()) {
return Mono.just(accessTokenNode.asText());
}
return Mono.empty();
} catch (IOException e) {
return Mono.error(e);
}
}
private Mono<Long> collectEndpointCount(String timeRange, String url) {
return getBearerToken()
.flatMap(bearerToken -> webClient.get()
.uri(url)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + bearerToken)
.retrieve()
.bodyToMono(String.class)
.flatMap(responseBody -> Mono.fromCallable(() -> processEndpointResponse(responseBody))))
.onErrorMap(ex -> ex instanceof WebClientResponseException || ex instanceof IOException,
BillProcessorExceptionCollect::new);
}
private long processEndpointResponse(@NonNull String responseBody) throws IOException {
try (JsonParser jsonParser = new JsonFactory().createParser(responseBody)) {
while (jsonParser.nextToken() != null) {
if (jsonParser.getCurrentToken() == JsonToken.FIELD_NAME
&& "values".equals(jsonParser.getCurrentName())) {
jsonParser.nextToken();
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
if (jsonParser.getCurrentToken() == JsonToken.VALUE_STRING) {
return (long) Double.parseDouble(jsonParser.getText());
}
}
}
}
}
return 0;
}
ResultsCollectorImplTest.java
@Mock
private WebClient webClient;
@Mock
private ApigeeConfig apigeeConfig;
@InjectMocks
private ResultStatsCollectorImpl resultStatsCollector;
@Mock
private RequestBodyUriSpec requestBodyUriSpec;
@Mock
private RequestHeadersUriSpec requestHeadersUriSpec;
@Mock
private RequestHeadersSpec requestHeadersSpec;
@Mock
private ResponseSpec responseSpec;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
ResultStatsCollector = new ResultStatsCollectorImpl(webClient, apigeeConfig);
}
@Test
void testCollectWithValidData() {
String timeRange = "08/01/2023 00:00~08/31/2023 23:59";
Mono<String> accessToken = Mono.just("{\"access_token\":\"bearer_token\"");
when(apigeeConfig.getRefreshToken()).thenReturn("mockRefreshToken");
when(webClient.post()).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.uri(anyString())).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.header(anyString(), anyString())).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.bodyValue(anyString())).thenReturn(requestHeadersSpec);
when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(accessToken);
String mockApiResponse = "{\"from\":\"2023-08-01T00:00:00+08:00\",\" count1\":100,\"count2\":100}";
when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri(anyString())).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.header(HttpHeaders.AUTHORIZATION, "mockAccessToken")).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just(mockApiResponse));
Mono<ResultStats> usageStats = resultStatsCollector.collect(timeRange);
StepVerifier.create(usageStats).verifyComplete();
}
1条答案
按热度按时间soat7uwm1#
当我的方法调用webClient时,每个方法都生成了不同的
responseSpec
。添加另一个mock ResponseSpec就可以了。