mike-neckのブログ

Java or Groovy or Swift or Golang

Spring WebFlux の Router Function のテスト

久々に Spring WebFlux を書いてたのだが、いまいちルーティングがうまくできず、 Routing Function に対してテストを書いてみることにした。

f:id:mike_neck:20180802004547p:plain

で、テストの書き方を調べてみたのだが、とりあえず何も見つからなかった(サーバーを起動するパターンは見つかったが、ルーターのテストごときでサーバーを起動したくない)ので、Reactor のテストの書き方をもとに強引に書いてみた。これが正しいのかどうかはわからない。


プロダクションコード

プロダクションコードはこんな感じ。

@Configuration
class Routing {

  private final MyHandler handler;

  Routing(final MyHandler handler) {
    this.handler = handler;
  }

  @Bean
  RouterFunction<ServerResponse> routerFunction() {
    return routes(GET("/foo"), handler::handle);
  }
}

テストコード

で、書いたテストコード。これはあくまでルーティングが意図したものになっているかを確認するテスト。というのも、ルーティングがうまくできていなかったからテストを書いたため。

@ExtendWith(SpringExtension.class)
@Import({Routing.class, MyHandler.class})
class RoutingTest {

  final Routing routing;

  @Autowired
  RoutingTest(final Routing routing) {
    this.routing = routing;
  }

  @Test
  void test() {
    final ServerRequest request =
      MockServerRequest.builder()
        .method(HttpMethod.GET)
        .uri(URI.create("/foo"))
        .build();

    final Mono<HandlerFunction<ServerResponse>>
      handler =
        routing
          .routerFunction()
          .route(request);

    StepVerifier.create(handler)
        .expectNextCount(1)
        .verifyComplete();
  }
}

なお、 URI については、かなりゆるい URI でもマッチする。具体的には http://bar-baz/foo でもマッチする。当然、 /foo/baz はマッチしない。ちなみに、マッチしない場合のテストの書き方はこんな感じ。

StepVerifier.create(handler)
    .verifyComplete();

余談、というか…

もともとは、パスに対して正規表現でマッチングする方法を調べてた。最初うまくできなかったが、次のようにやればよいらしい。

return route(GET("/{foo:[a-zA-Z0-9]+}"), handler::handle);