Testing request sending and receiving logic with MockWebServer in JUnit

I had the opportunity to implement a function using an external API in a Java application, so talk about that time.

Thing you want to do

When request transmission / reception processing is newly implemented, it makes me want to check whether the expected operation is performed with a fixed response. So I decided to use a library called MockWebServer to return a fixed response. This simplifies the logic verification of the request sending and receiving part.

mockserver.png

Development environment

The Java environment to try this time is as follows.

$ java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)

It is assumed that the build tool is using maven (3.6.0).

How to Use

Add the required library to pom.xml.

<dependency>
  <groupId>com.squareup.okhttp</groupId>
  <artifactId>mockwebserver</artifactId>
  <version>2.7.5</version>
  <scope>test</scope>
</dependency>

You need to import MockWebServer and MockResponse to implement.

A class that provides a mechanism for MockWebServer to receive a request and return a response. MockResponse is a class used to define a dedicated response content.

At a minimum, the implementation is as follows to run MockWebServer.

import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

public class QiitaTest {
    
    private MockWebServer mockWebServer;
    
    @Before
    public void setup() throws IOException {
        this.mockWebServer = new MockWebServer();
        this.mockWebServer.start();
    }

    @Test
    public void qiitaTest() {
        String json = "{\"message\": \"Test for qiita\"}";
        MockResponse mockResponse = new MockResponse();
        mockResponse.setBody(json);
        mockResponse.setResponseCode(200);
        this.mockWebServer.enqueue(mockResponse);
        
        String mockServerUrl = mockWebServer.url("/").toString();
        // mockServerUrl = http://localhost:59690/
        
        //Write the request transmission process, receive the response and write the test content
    }
}

To start a dummy server, create an instance of MockWebServer and call the start method. Although not used here, it is possible to specify the port as an argument of the constructor. Since mockWebServer.start () has IOException specified in throws, setup () defined as preprocessing does the same.

This makes it possible to verify the process of mapping the response content to an object using Jackson etc. with a fixed response.

You can try normal processing as described above, but you can use setBodyDelay to arbitrarily delay the response.

import import java.util.concurrent.TimeUnit;
...
    @Test
    public void qiitaDelayTest() {
        String json = "{\"message\": \"10 seconds late\"}";
        MockResponse mockResponse = new MockResponse();
        mockResponse.setBody(json);
        mockResponse.setBodyDelay(10, TimeUnit.SECONDS);
        mockResponse.setResponseCode(200);
        this.mockWebServer.enqueue(mockResponse);
        ...        
    }

You can set a timeout in the request transmission process and try error handling when the threshold is exceeded on purpose.

In the Unit test, the test is executed by explicitly creating json like this and sending the request, but with MockServer started up behind the scenes, run the application that directs the request to MockServer. , It is also possible to check the operation.

Finally

Thanks to MockWebServer, I was able to easily check the operation by specifying the response. Since the test code itself was unfamiliar, there may be mistakes, but it was the method when I verified the operation of the logic via the external API.

Recommended Posts

Testing request sending and receiving logic with MockWebServer in JUnit
Getting Started with Parameterization Testing in JUnit
Sample code for basic mocking and testing with Mockito 3 + JUnit 5
Start UI testing with Dagger2 and Mockito
Control test order in Junit4 with enumeration