Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

junit - Mock API responses in JUnit5 based tests using mockito: java.lang.NullPointerException

Context

I am completely new to Java / JUinit and I have some trouble understanding how to mock the following API response. In this Extractor class, I have a method getManagers (later to be used as a factory method to return 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();
}

To get more familiar with Mockito, I started with a trivial test. The point is to be able to write tests execution of which should not depend on the REST API being actually called. testGetManagers check that getManagers returns the same json body as the one loaded from, apiResponse1.json (I checked that apiResponse1.json is properly loaded)

@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);
        .....

Issue

It looks like I failed to properly mock response.body(), for I end up with

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)
....

I think that the problem comes from what I include in @Mock (tried several combinaisons). I probably mis-transposed the logic of how I handle these cases in pytest to org.mockito.Mockito. When I only include HttpResponse response; in @Mock, I get a org.mockito.exceptions.misusing.UnnecessaryStubbingException I do not entirely understand.

What should I include in @Mock to inject this Json file when response.body() is called? Should I mock 'one degree before' (response or HttpResponse<String> response)?

Environnement

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to put @Mock annotation before each field

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...