java - 运行测试用例 ClientHttpResponse 时抛出 401 错误
问题描述
我的单元测试有问题。在我的单元测试中,我得到 401 Unauthorized作为响应状态,我不知道如何解决这个问题。这不是一个 Spring 项目。
我的测试课
@RunWith(MockitoJUnitRunner.class)
public class LTest {
@Test
public void test_retrieve() throws Exceptions{
CloseableHttpClient mockHttpClient = mock(CloseableHttpClient.class);
CloseableHttpResponse mockHttpResponse = mock(CloseableHttpResponse.class);
HttpEntity mockEntity = mock(HttpEntity.class);
StatusLine mockStatusLine = mock(StatusLine.class);
when(mockHttpClient.execute(new HttpGet(new URIBuilder(anyString()).build()))).thenReturn(mockHttpResponse);
when(mockHttpResponse.getEntity()).thenReturn(mockEntity);
when(mockHttpResponse.getStatusLine()).thenReturn(mockStatusLine);
when(mockStatusLine.getStatusCode()).thenReturn(HttpStatus.SC_OK);
Map<String, Employee> map = sample.retrieve();
assertNotNull(map);
assertEquals(1,map.size());
}
上述测试用例的源代码
CloseableHttpClient httpClient = HttpClientUtils.setupClient(HttpClientBuilder.create()).build();
String url = "http://someexample.com";
UriBuilder builder = new URIBuilder(url)
.setParameter("limit",5)
.setParameter("centre",centre);
CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(builder.build()));
if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
try{
String entity = EntityUtils.toString(httpResponse.getEntity());
ObjectNode node = new ObjectMapper().readValue(entity,ObjectNode.class);
} catch (IOException e){
e.printStackTrace();
}
}
在运行测试用例时,它显示断言错误,因为它正在通过 catch 块,因为下面的行抛出 401 而不是 200
CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(builder.build()));
谁能帮我解决我遇到的上述错误?
解决方案
在测试中,HTTPClient
没有被嘲笑,这就是失败的原因。
为了模拟,HTTPClient
我们可以遵循以下策略
getHttpClient()
在 ClassToBeTested 中提取为
public class HttpClientToBeTested {
public Map retrieve() throws URISyntaxException, IOException {
CloseableHttpClient httpClient = getHttpClient();
String url = "http://someexample.com";
URIBuilder builder = new URIBuilder(url)
.setParameter("limit","5")
.setParameter("centre","centre");
CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(builder.build()));
if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
try{
String entity = EntityUtils.toString(httpResponse.getEntity());
//ObjectNode node = new ObjectMapper().readValue(entity,ObjectNode.class);
Map node = new ObjectMapper().readValue(entity, Map.class); // Assume ObjectNode is a custom class, so for demo using Map.
return node;
} catch (IOException e){
e.printStackTrace();
throw e;
}
}
return null;
}
// New extracted method that will be mocked in the test case
protected CloseableHttpClient getHttpClient() {
return HttpClientBuilder.create().build();
}
}
- 接下来在测试类中,我们可以通过在匿名类中继承 ClassToBeTested 来注入模拟,如下所示。
@Test
public void test_retrieve() throws Exception {
CloseableHttpClient mockHttpClient = mock(CloseableHttpClient.class);
CloseableHttpResponse mockHttpResponse = mock(CloseableHttpResponse.class);
//HttpEntity mockEntity = mock(HttpEntity.class); Not required since we will pass actual entity
StatusLine mockStatusLine = mock(StatusLine.class);
when(mockHttpClient.execute(new HttpGet(new URIBuilder(anyString()).build()))).thenReturn(mockHttpResponse);
when(mockHttpResponse.getEntity()).thenReturn(new StringEntity("{\"key\":\"value\"}")); // Important: Pass your actual response as string here.
when(mockHttpResponse.getStatusLine()).thenReturn(mockStatusLine);
when(mockStatusLine.getStatusCode()).thenReturn(HttpStatus.SC_OK);
// Code to mock the http client
HttpClientToBeTested sample = new HttpClientToBeTested() {
@Override
protected CloseableHttpClient getHttpClient() {
return mockHttpClient;
}
};
Map map = sample.retrieve();
assertNotNull(map);
assertEquals(1,map.size());
}
更新:模拟 httpClient 后,httpClient.execute()
应该返回SC_OK
. 但是,发布反序列化响应将失败,因为模拟HttpEntity
将返回 null。为了避免它,我们宁愿发送一个StringEntity
. 用详细信息更新了实际和测试类。
推荐阅读
- react-native - 如何使用蓝牙打印机 react-native 打印数据?
- salt-stack - saltstack 和常见依赖项
- python - cuDNN 初始化失败
- laravel - 带有 vagrant 和 virtualbox 的 laravel - 安装了 10 版,但“vagrant up”时安装了 11
- javascript - 如何将“else”语句的值添加到之前的“if”?
- r - 在嵌套数据(嵌套命名列表的小标题)中,我如何根据嵌套值的存在来改变某个深度级别的新列
- sql - 从第二次出现获取值
- tooltip - 溢出小网格时,Ag-Grid Tooltip 部分隐藏
- html - 如何在javascript中单击按钮时从一个html页面重定向到另一个页面?
- updates - GLib 文档说 g_file_has_key() 已被弃用,因为它使用 GError,但新的替换函数在哪里?