【问题标题】:Mock API responses in JUnit5 based tests using mockito: java.lang.NullPointerException使用 mockito 在基于 JUnit5 的测试中模拟 API 响应:java.lang.NullPointerException
【发布时间】:2021-04-16 09:08:13
【问题描述】:

上下文

我对 Java / JUinit 完全陌生,我在理解如何模拟以下 API 响应时遇到了一些麻烦。在这个Extractor类中,我有一个方法getManagers(后来作为工厂方法返回List<Manager>

public class Extractor {
    ....
    public String getManagers(HashMap parametters, String base_url, String token) throws IOException, InterruptedException {

        HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_2).build();
        HttpRequest request = HttpRequest
                .newBuilder(URI.create(String.format("%s/api/rest/query/HUB_REFERENTIALS/Employee/GD%s", base_url, assembleSemQL(parametters))))
                .header("API-Key", token).GET().build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

        return response.body();
}

为了更加熟悉 Mockito,我从一个琐碎的测试开始。关键是能够编写不依赖于实际调用的 REST API 的测试执行。 testGetManagers 检查 getManagers 是否返回与从 apiResponse1.json 加载的相同的 json 主体(我检查了 apiResponse1.json 是否正确加载)

@ExtendWith(MockitoExtension.class)
public class ExtractorTest {
    Extractor extractor = new Extractor();

    @Mock
    HttpClient client;
    HttpResponse response;
    HttpRequest httpRequest;

    @Test
    public void testGetManagers() throws IOException, InterruptedException {

        HashMap<String, String> parametters = new HashMap<String, String>();
        parametters.put("SrcGender", "F");
        // Here        
        Mockito.when(response.body()).thenReturn(Resources.toString(Resources.getResource("apiResponse1.json"), Charsets.UTF_8));

        String response = extractor.getManagers(parametters);
        .....

问题

看起来我未能正确模拟 response.body(),因为我最终得到了

java.lang.NullPointerException
    at com.comecompany.cockpit.ExtractorTest.testGetManagers(ExtractorTest.java:55)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
....

我认为问题来自我在@Mock 中包含的内容(尝试了几种组合)。我可能将我在pytest 中处理这些案例的逻辑错误地转换为org.mockito.Mockito。当我只在@Mock 中包含HttpResponse response; 时,我得到一个org.mockito.exceptions.misusing.UnnecessaryStubbingException 我不完全理解。

当调用response.body() 时,我应该在@Mock 中包含什么来注入这个Json 文件?我应该嘲笑“前一学位”(responseHttpResponse&lt;String&gt; response)吗?

环境

  • openjdk11
  • mockito-junit-jupiter 2.23.0
  • junit-jupiter-api 5.7.0

【问题讨论】:

    标签: java junit mocking mockito junit5


    【解决方案1】:

    需要在每个字段前加上@Mock注解

    @Mock
    HttpClient client;
    @Mock
    HttpResponse response;
    @Mock
    HttpRequest httpRequest;
    

    【讨论】:

    • 它解决了异常问题,但response.body() 似乎没有被嘲笑——也就是说,我似乎从实际的 API 而不是 apiResponse1.json 得到响应
    • 如果您正在调用实际的 API,您将得到它的响应。你需要在这里做类似stackoverflow.com/questions/25564533/…
    • 我认为org.mockito.Mockito 像补丁一样工作(如python 的MagikMock)。我可能错了
    • 我正在尝试类似的事情,但我在嘲笑client.send(request, HttpResponse.BodyHandlers.ofString());,所以我可以返回带有所有我想要的响应信息的实际结果; 201 状态、正文、标题等。但是,我无法模拟结果,因为它需要 CompletableFuture 并且我没有设法为它正确创建对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多