Java 运行测试用例时,ClientHttpResponse抛出401错误

Java 运行测试用例时,ClientHttpResponse抛出401错误,java,unit-testing,junit,mockito,Java,Unit Testing,Junit,Mockito,我的单元测试有问题。在我的单元测试中,我得到了401未经授权的响应状态,我不知道如何解决这个问题。这不是一个Spring项目 我的测试班 @RunWith(MockitoJUnitRunner.class) public class LTest { @Test public void test_retrieve() throws Exceptions{ CloseableHttpClient mockHttpClient = mock(CloseableHttp

我的单元测试有问题。在我的单元测试中,我得到了401未经授权的响应状态,我不知道如何解决这个问题。这不是一个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());
    }
在运行测试用例时,它显示断言错误,因为它要通过catch块,因为下面的行抛出的是401而不是200

CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(builder.build()));

有人能帮我解决我遇到的上述错误吗?

在测试中,
HTTPClient
没有被模拟,这就是失败的原因

要模拟
HTTPClient
,我们可以遵循以下策略

  • 提取类中的
    getHttpClient()
    ,测试为
  • 接下来在test类中,我们可以通过在匿名类中对ClassToBeTested进行子类化来注入mock,如下所示


  • 更新:模拟httpClient后,
    httpClient.execute()
    应返回
    SC\u OK
    。但是,由于mock
    HttpEntity
    将返回null,因此反序列化响应将失败。为了避免它,我们宁愿发送一个
    StringEntity
    。使用详细信息更新了实际类和测试类。

    您没有模拟http客户端
    CloseableHttpClient httpClient=HttpClientUtils.setupClient(HttpClientBuilder.create()).build()。一个选项是将此行提取到一个单独的
    getHttpClient()
    方法。Mock或override方法并传递
    mockHttpClient
    是的,我发现这一行已经在产生问题,但是如何Mock或override我不知道。我对写测试用例还不熟悉,像这样的事情我需要做吗
    @Override protected HttpClient getHttpClient(){return mockHttpClient;}
    我添加了一个答案,看看它是否适合您的场景?@Override正在抛出错误。方法不重写其超类中的方法。它对我没有帮助。仍然存在相同的问题。请向上滚动,问题中已经提到了代码。当我尝试模拟httpClient时,测试用例抛出了NullPointerException,谢谢,它成功了。我在顶部声明了CloseableHttpResponse httpResponse,然后尝试访问else块中的对象。这就是问题的根源。
    CloseableHttpResponse httpResponse = httpClient.execute(new HttpGet(builder.build()));
    
    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();
        }
    }
    
    @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());
    }