WebFluxのFluxレスポンスをテストする

はじめに

表題通りなんですが、よくやり方を忘れるのでメモしておきます。

手順

手順としては簡単で

1.WebTestClient.ResponseSpectのreaurnResultを呼び出し、FluxExchangeResultを受け取る。
2. FluxExchengeResultのgetResponseBody()を呼び出してFluxを取り出し、StepVerifierのcreate()に渡す

以上です。

やってみる

環境

$ java --version
openjdk 14.0.1 2020-04-14
OpenJDK Runtime Environment (build 14.0.1+7)
OpenJDK 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)

$ mvn --version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
.
.

SpringBootのバージョンは2.3.3.RELEASEです。

テスト対象を実装する

まずはテスト対象のハンドラーとDTOの実装です。
ハンドラーはFluxをレスポンスとして返します。

Employee.java

public class Employee{

    private String name;

    public Employee() {
    }

    public Employee(String name) {
        this.name = name;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override public boolean equals(Object o) { if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return Objects.equals(name, employee.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

EployeeHandler.java

@Component
public class ExampleHandler {

    public Mono<ServerResponse> getEmployees(ServerRequest serverRequest) {
        return ServerResponse.ok().body(Flux.just(new Employee("henoheno"), new Employee("moheji")), Employee.class);
    }

次にハンドラーをRouterFunctionに登録します。 WebfluxApplication .java

@SpringBootApplication
public class WebfluxApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebfluxApplication.class, args);
    }

    @Bean
    public RouterFunction<ServerResponse> route(ExampleHandler exampleHandler) {
        return RouterFunctions.route(GET("employees"), exampleHandler::getEmployees);
    }
}

起動してカールを叩いてみます。

$ curl localhost:8080/employees
[{"name":"henoheno"},{"name":"moheji"}]

ここまではOKそうですね。

テストを書く

上記の手順でテストを実装すると以下のようになります。

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class WebfluxApplicationTests {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    void getEmployee() {
        FluxExchangeResult<Employee> result = webTestClient.get().uri("/employees")
                .exchange()
                .expectStatus().isOk()
                .returnResult(Employee.class);

        StepVerifier.create(result.getResponseBody())
                .expectNext()
                .expectNextMatches(employee -> employee.equals(new Employee("henoheno")))
                .expectNextMatches(employee -> employee.equals(new Employee("moheji")))
                .expectComplete()
                .verify();
    }
}

FluxをStepVerifier.create()に渡してしまって後は煮るなりやくなりって感じですね。