16 May 2020

Spring Boot Reactive Testing Part 1



I was worked in spring 4 in the last couple of years. Then I thought to learn reactive spring using spring 5. Then I thought to write an article that I have discovered new in reactive programming testing.

Here I will not explain how to write reactive rest endpoints. Here It will explain how to test different kinds of scenarios. In this thread I will explain how to test data repository & reactive API endpoint. Next tutorial I will explain how to test reactive client

It is like same in synchronous mongo client. First write repository & then using that repository we can write a simple JUnit test. Here I have used StepVerifier to validate the response.

import dev.innova.mockito.mockitoserver.domain.UserData;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.test.context.junit4.SpringRunner;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;

@DataMongoTest
@RunWith(SpringRunner.class)
public class UserDataRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void testUserQuery() {

        Flux<UserData> userDataFlux = this.userRepository.deleteAll()
                .thenMany(Flux.just("sajith", "sajith", "sajith2", "sajuth3")
                .flatMap(item -> this.userRepository.save(new UserData(null, item, item)))
                .thenMany(this.userRepository.findByName("sajith")));

        StepVerifier.create(userDataFlux)
                .expectNextCount(2)
                .verifyComplete();
    }
}

As the first step I have created a User Resource configuration. It will return the user list.

import dev.innova.mockito.mockitoserver.domain.UserData;
import dev.innova.mockito.mockitoserver.repository.UserRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;

import static org.springframework.web.reactive.function.server.RequestPredicates.GET;

@Configuration
public class UserResourceConfiguration {

    @Bean
    RouterFunction<ServerResponse> routes(UserRepository userRepository) {
        return RouterFunctions.route(GET("/allUsers"), request -> ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON).body(userRepository.findAll(), UserData.class));
    }
}


Then using mockito we can mock the object & methods. Then using WebTestClient test case like below.


import dev.innova.mockito.mockitoserver.config.UserResourceConfiguration;
import dev.innova.mockito.mockitoserver.domain.UserData;
import dev.innova.mockito.mockitoserver.facade.ClassifiedService;
import dev.innova.mockito.mockitoserver.repository.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Flux;

@WebFluxTest
@Import(UserResourceConfiguration.class)
@RunWith(SpringRunner.class)
public class AddsRestApiTest {

    @MockBean
    private UserRepository userRepository;

    @Autowired
    private WebTestClient webTestClient;

    @MockBean
    private ClassifiedService classifiedService;

    @Test
    public void getAllAddsTest() throws Exception {

        UserData add1 = new UserData();
        add1.setId("001");
        add1.setName("Sample1");

        UserData add2 = new UserData();
        add2.setId("002");
        add2.setName("Sample2");

        UserData add3 = new UserData();
        add3.setId("003");
        add3.setName("Sample3");

        Mockito.when(this.userRepository.findAll())
                .thenReturn(Flux.just(add1, add2, add3));

        this.webTestClient.get()
                .uri("http://localhost:8084/allUsers")
                .exchange()
                .expectStatus().isOk()
                .expectBody().jsonPath("@.[0].id").isEqualTo("001");

    }
}

Code base available in here.If you have any suggestions or questions put comments here.