我正在尝试创建一个全局Web客户端重试过滤器,并尝试通过Mockito对其进行单元测试。筛选器是ExchangeFilterFunction的实现。我使用的技术提出了here。
我使用的是Sping Boot 3.0.6版本和Java temurin 17。
RetryStrategyFilter
@Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
return next.exchange(request)
.flatMap(clientResponse -> Mono.just(clientResponse)
.filter(response -> {
final HttpStatusCode code = clientResponse.statusCode();
boolean isRetryable = Boolean.FALSE;
if (code.isError()) {
//check if its a retryable error
isRetryable = Arrays.stream(DEFAULT_RETRYABLE_ERROR_CODES).anyMatch(defaultCode -> defaultCode == code.value()) ||
(retryFilterConfiguration.getRetryErrorCodes() != null &&
retryFilterConfiguration.getRetryErrorCodes().stream().anyMatch(retryErrorCode -> retryErrorCode == code.value()));
LOGGER.warn("Request Failed. Retrying -> url={}; status={}", request.url(), code.value());
}
return isRetryable;
}) // if no errors, filter it out
.flatMap(response -> clientResponse.createException()) // let's raise an exception if response was an error
.flatMap(Mono::error) // trigger onError signal
.thenReturn(clientResponse)
)
.retry(retryFilterConfiguration.getRetryCount());
}
RetryStrategyFilterTest
@DisplayName("Retry on Default Error Code")
@Test
public void defaultRetryableErrorCode(){
//ARRANGE
ClientRequest mockRequest = Mockito.mock(ClientRequest.class);
ExchangeFunction mockNext = Mockito.mock(ExchangeFunction.class);
ClientResponse mockResponse = Mockito.mock(ClientResponse.class, RETURNS_DEEP_STUBS);
int tooManyRequestsErrorCode = HttpStatus.TOO_MANY_REQUESTS.value();
when(mockNext.exchange(mockRequest)).thenReturn(Mono.just(mockResponse));
when(mockResponse.statusCode()).thenReturn(HttpStatusCode.valueOf(tooManyRequestsErrorCode));
//ACT
retryStrategyFilter.filter(mockRequest,mockNext);
//ASSERT
verify(mockResponse,times(0)).createException();
verify(retryFilterConfiguration,times(1)).getRetryCount();
}
当使用默认的可重试错误代码(429)对代码进行单元测试时,我希望它调用retry,但我得到了以下存根错误。
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
1. -> at org.mycomp.http.filter.RetryStrategyFilterTest.defaultRetryableErrorCode(RetryStrategyFilterTest.java:37)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
这意味着Mono.just(clientResponse)
的filter
函数没有被调用,当我调试它时,我注意到我无法单步执行它。我跟踪的一个线索是,我在测试中有这一行when(mockNext.exchange(mockRequest)).thenReturn(Mono.just(mockResponse));
,在过滤器函数.flatMap(clientResponse -> Mono.just(clientResponse)
中有这一行。我在这里筑巢吗?这可能是它不起作用的原因吗?
1条答案
按热度按时间w8rqjzmb1#
可以使用
@RunWith(MockitoJUnitRunner.Silent.class)
。这个Mockito JUnit Runner实现 * 忽略 * stubbing参数不匹配(MockitoJUnitRunner.StrictStubs)并且 * 不检测 * 未使用的stubbing。”””但这不是一个解决方案!**
最好是修改你的测试。检测到不必要的存根-意味着您使用了不必要的when()存根,因此您需要删除它或使用lenient()来停止异常。
顺便说一下,你的代码看起来很奇怪。也许我们需要重构一些?在你的代码中,flatMap接受Mono和Publisher类型,所以我们可以很容易地返回mock response而不是Mono.just(mockResponse)。删除嵌套monos:
通过简化这些代码,所有的都应该工作。