gpt4 book ai didi

java - 如何使用 junit mockito 覆盖匿名类重写方法

转载 作者:行者123 更新时间:2023-11-30 12:04:22 24 4
gpt4 key购买 nike

我有以下代码根据响应代码重试请求。

public class Sample {
public static HttpClient getInstance() {
HttpClientBuilder builder = HttpClients.custom();
builder.setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
int waitPeriod = 200;

@Override
public boolean retryRequest(final HttpResponse response, final int executionCount,
final HttpContext context) {

int statusCode = response.getStatusLine().getStatusCode();
return ((statusCode == 429)&& (executionCount < 3));
}

@Override
public long getRetryInterval() {
return waitPeriod;
}
});

return builder.build();

}
}

虽然我正在为这个 getInstance 方法编写单元测试,但是覆盖的方法 (retryRequest, getRetryInterval) 没有被覆盖。我如何编写单元测试来覆盖这些方法。通过谷歌搜索,我发现我们可以使用 ArgumentCaptor。我试过下面的代码,但它不起作用。

import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ServiceUnavailableRetryStrategy;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@WebAppConfiguration
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:context.xml"})
@PrepareForTest({ HttpClients.class, Sample.class})
public class Sample {

@Mock
HttpClientBuilder clientBuilderMock;

@Mock
CloseableHttpClient clientMock;

@Mock
HttpResponse responseMock;

@Mock
HttpContext contextMock;

@Mock
StatusLine statusLineMock;

@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(HttpClients.class);
}

@Test
public void test() throws Exception {
when(HttpClients.custom()).thenReturn(clientBuilderMock);
when(clientBuilderMock.build()).thenReturn(clientMock);
when(responseMock.getStatusLine()).thenReturn(statusLineMock);
when(statusLineMock.getStatusCode()).thenReturn(429);

Sample.getInstance();

ArgumentCaptor<ServiceUnavailableRetryStrategy> argumentCaptor = ArgumentCaptor.forClass(ServiceUnavailableRetryStrategy.class);
verify(clientBuilderMock).setServiceUnavailableRetryStrategy(argumentCaptor.capture());
ServiceUnavailableRetryStrategy retryStrategy = argumentCaptor.getValue();
retryStrategy.retryRequest(responseMock, 3, contextMock);
}

}

argumentCaptor.capture() 总是给我 null。我越来越喜欢

org.mockito.exceptions.base.MockitoException: No argument value was captured! You might have forgotten to use argument.capture() in verify()... ...or you used capture() in stubbing but stubbed method was not called. Can anyone help me on this. I would like to test the retryRequest method functionality.

最佳答案

编辑:改写答案以使其更易于阅读。


  1. 应该由 PowerMockito 处理的类需要在 @PrepareForTest 注释中声明。

  2. 如果注释用于创建模拟,则所有未在 @PrepareForTest 注释中声明的注释类都由 Mockito 创建。

  3. 如果注释用于创建模拟并调用 MockitoAnnotations.initMocks(this);,这显然会导致声明被覆盖,所有模拟都由 Mockito 创建。(来源:https://groups.google.com/forum/#!topic/powermock/yPBey4hr7IU)

  4. Mockito 无法处理静态或 final方法。
    模拟操作可能会静默失败。


问题的根源在于 HttpClientBuilder#setServiceUnavailableRetryStrategy 是一个final 方法,因此不能由 Mockito 处理。

解决方案是 HttpClientBulder 的 Mock 必须由 PowerMockito 处理。按照1.需要在@PrepareForTest注解中声明。

@PrepareForTest({ HttpClients.class, HttpClientBuilder.class, Sample.class})


如果您想使用注释来创建模拟,您不得调用

MockitoAnnotations.initMocks(this);

(参见 2./我用最新的 powermockito 版本 (1.7.4/2.0.2) 验证了这个问题)


否则您必须手动创建模拟。

HttpClientBuilder clientBuilderMock = PowerMockito.mock(HttpClientBuilder.class);

关于java - 如何使用 junit mockito 覆盖匿名类重写方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57166142/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com