LoginSignup
0
0

More than 3 years have passed since last update.

Spring Data JPAのWeb supportを使ったハンドラメソッドをテストする方法

Last updated at Posted at 2019-08-23

はじめに

この記事はSpring Data JPAが提供するWeb supportの「@PathVariableのid検索して引数に設定してくれる」機能を使っている場合に、そのハンドラメソッドをどうやってテストすればいいかを説明したものです。記事中で説明しているコードは以下に置いてあります。
https://github.com/junjis0203/spring-jpa-web-unittest

Spring Data JPAのWeb support

Spring Data JPAにはWeb support機能があります。これを使うと、

UserController.java抜粋
    @GetMapping("/users/{id}")
    public User show(@PathVariable("id") User user) {
        return user;
    }

このように自分でidからUserエンティティを検索しなくていいのでハンドラメソッドを非常にシンプルにできます。なお裏側はUserクラスに対応するRepository使って検索しているのでRepositoryインターフェース自体は必要です。

よしではテストするぞ

・・・どうやって(。´・ω・)?
検索されるエンティティはどう準備すればいいの?Spring Data JPAみたいに@DataJpaTest付けてTestEntityManager使う?idは?自分で指定しておけばいい?

まあ出てきたエラー見てから考えるか、てことでテストを作成、

UserControllerTest.java抜粋
    @Test
    public void userExists() throws Exception {
        mockMvc.perform(get("/users/{id}", "1"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("name", is("alice")));
    }

実行。なおgithubに置いてあるのは最終形なので同じようなエラーが出ることを確認したい人はConfigクラスに付いている@TestConfiguration外してください。

java.lang.AssertionError: Status expected:<200> but was:<500>

コンソールの方にはこんなのが出ていた(長いので適当に改行)。やはりSpring Data JPAのWeb supportは動かないようだ。

2019-08-23 22:55:51.036  WARN 8140 --- [           main] 
.w.s.m.s.DefaultHandlerExceptionResolver : 
Resolved [org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: 
Failed to convert value of type 'java.lang.String' to required type 'com.example.demo.User'; 
nested exception is java.lang.IllegalStateException: 
Cannot convert value of type 'java.lang.String' to required type 'com.example.demo.User': 
no matching editors or conversion strategy found]

本題:テストをするためのセットアップ

テスト環境でWeb supportが動かないからと言ってControllerにRepositoryをDIさせたくないし何か方法はないかと「spring jpa pathvariable test」で検索したところ以下のページが引っかかりました。
https://stackoverflow.com/questions/40240547/combine-webmcvtest-with-pathvariable-annotated-controllers-in-spring-boot-1-41

なるほどWebMvcConfigurer.addFormattersで登録すればいいのか。
というわけでこれを参考にテストを書いていたのですが、複数のエンティティが必要な状況に遭遇したのでもう少しかっこいいConverterにしました。

UserControllerTest.java抜粋
    private static Map<String, User> userMap;

    @Before
    public void setUp() {
        userMap = new HashMap<>();
        userMap.put("1", User.builder().name("alice").mail("alice@example.com").build());
    }

    @TestConfiguration
    static class Config implements WebMvcConfigurer {

        @Override
        public void addFormatters(FormatterRegistry registry) {
            // emulate Spring Data JPA Web support
            registry.addConverter(String.class, User.class, id -> userMap.get(id));
        }

    }

やっていることは

  • StringとUserの対応Mapを@Before付けたメソッドで用意。@BeforeClassでもいい気はするけどテストごとにリセットされる方がいい気もする
  • ConverterはMap使って返すだけ(Stack Overflowでは存在しないidに対してIllegalArgumentException投げてるけど「本物」の挙動的にはnull返す方が正しい)
  • static classが参照できるようにMapもstaticにしないといけないのがダサいが仕方ない

ともかくこれでテストができました。

おわりに

今回はSpring Data JPAが提供するWeb supportを使ってる場合にどうやってテストすればいいのかを説明しました。
公式にテストする方法用意しておいてくれよと思うのですが、だったら自分で作ってプルリク送るのがいいのですかね。Springの動作理解して適切な「設定の書き方」構築するまで相当かかりそうですが・・・

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0