絶対後で忘れるので、備忘のため投稿。
SpringBootでMockMvcを使ったテストを行っていた際、Controllerクラス内にある@AutowiredしたServiceクラスがNullPointerExceptionになりました。
最初はスタンドアロンでテストしていたので、以下のように記述していました。
public class 〇〇ControllerTest { private MockMvc mockMvc; @Before public void before() throws Exception { mockMvc = MockMvcBuilders.standaloneSetup(new 〇〇Controller()).build(); } @Test public void てすと() throws Exception { mockMvc.perform(post("/path") .andExpect(status().isOk()); } }
しかしServiceクラスやRepositoryクラスなど、@Autowiredを使った構成にしたところ上記のNullPointerExceptionが発生。
対応策は以下2点。
・サーバー起動でテストする
・@AutowiredでDIされるクラスを呼び出す、MockMvc自体もDIする
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc public class 〇〇ControllerTest { @Autowired private MockMvc mockMvc; @Before public void before() throws Exception { // mockMvc = MockMvcBuilders.standaloneSetup(new 〇〇Controller()).build(); } @Test public void てすと() throws Exception { mockMvc.perform(post("/path") .andExpect(status().isOk()); } }
うーん、DI慣れてないから。。。
【追記(2019/6/21)】
以下2点、備忘のため記録。
①tymeleafの循環ビューエラー
tymeleafを使用している場合、MockMVCはHTMLファイルテンプレートの場所やページファイルの拡張子が.htmlであることを理解してくれないようです。そのため、循環ビューが発生しているなどのエラーが吐かれます。
明示的にコンテキスト(WEBアプリの状況)を設定してあげれば解決します。
例)
@Autowired WebApplicationContext wac; @Before public void before() throws Exception { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/templates"); viewResolver.setSuffix(".html"); StudentLearnController()).setViewResolvers(viewResolver).build(); mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); }
②MockMVCの動作オプション
MockMVCは以下2つの動作オプションを持っています。
(1)webAppContextSetup
(2)standaloneSetup
私はとりあえずテストを厳密にする予定がないのでwebAppContextSetupを使用していますが、こちらは通常起動した時と同じような挙動でテストが行えます。
standaloneSetupを使用する場合はControllerクラス内でDIしているコンポーネントに色々設定が必要な様子。今のところwebAppContextSetupを使えばいいという状況ですが、いずれstandaloneSetupを使う必要性がでてきたら、改めて調べる予定で。。。
※参考URL10.2.4. 単体テストで利用するOSSライブラリの使い方 — TERASOLUNA
[/bash]