Priyanka Wagh
Priyanka Wagh

Reputation: 695

How can I use MockWebServer for Junit test cases of webclient?

I have a spring-boot application which calls some third party URL (let's say http://example.com/someUri) using webclient(I have used application-dev.properties for injecting this url in my application to achieve loose coupling) and consumes the response and use it in my application.

It's my first time when I am going to write test cases for webclient. and there I used @SprintBootTest. I found that there are two ways where I can test my webclient with third party Api call by mocking the api call and make it call to my local url(which will be using url(http://localhost:{portNumber}/someUri) from my testing properties file: src/test/resources/application.properties) where It will be giving some mockedResponse in return to my real client:

  1. Using wiremock
  2. Using MockWebServer

consider above code for better understanding:

@Service
Class SampleService{
    
@Value("${sample.url}")
private String sampleUrl;

public String dummyClient() {
    String sample =webClient.get()
            .uri(sampleUrl)
            .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .retrieve()
            .bodyToMono(String.class)
            .block();
    return sample;

    }
 }

application-dev.properties:

sample.url:http://example.com/someUri

src/test/resouces/application.properties:

http://localhost:8090/someUri

Testing class:

@SpringBootTest
public class sampleTestingClass {

@Autowired
private SampleService sampleService;

@Value("${sample.url}")
private String sampleUrl;

    public static MockWebServer mockWebServer = new MockWebServer();

    @BeforeAll
    static void setUp() throws IOException {
        mockWebServer.start(8090);
    }

    @AfterAll
    static void tearUp() throws IOException {
        mockWebServer.close();
    }

 HttpUrl url = mockWebServer.url("/someUri");
       
        mockWebServer
                .enqueue(
                new MockResponse()
                .setResponseCode(200)
                .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                        .setBody("Sample Successful")); 

      
        String sample = sampleService.dummyClient();
        assertEquals(sample ,matches("Sample Successful"));
    } 
}

but this code isn't working. it's giving me above error:

java.lang.NullPointerException 

It will be really helpful if anybody knows how this can be fixed to achieve my unit testing using mocked Url? Thanks in advance!

Upvotes: 4

Views: 15983

Answers (1)

rieckpil
rieckpil

Reputation: 12021

Here is a working example:

@Component
public class QuotesClient {

  private final WebClient webClient;

  public QuotesClient(WebClient.Builder builder, @Value("${client.baseUrl}") String baseUrl) {
    this.webClient = builder.baseUrl(baseUrl).build();
  }

  public JsonNode getData() {
    return this.webClient
      .get()
      .retrieve()
      .bodyToMono(JsonNode.class)
      .block();
  }
}

Using the WebClient.Builder is optional.

The corresponding test can look like the following:

class QuotesClientTest {

  private QuotesClient quotesClient;
  private MockWebServer server;

  @BeforeEach
  public void setup() {
    this.server = new MockWebServer();
    this.quotesClient = new QuotesClient(WebClient.builder(), server.url("/").toString());
  }

  @Test
  public void test() {

    server.enqueue(new MockResponse()
      .setStatus("HTTP/1.1 200")
      .setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}")
      .addHeader("Content-Type", "application/json"));

    JsonNode data = quotesClient.getData();
    assertNotNull(data);

    System.out.println(data);

  }

}

If you are searching for a similar setup using WireMock, Spring Boot, and JUnit 5, take a look at the linked guide.

Upvotes: 3

Related Questions