Spring FrameworkのUnitテスト実装方法 3-2.Controllerテスト(Junit4, spring-test, MockMvc(StandaloneSetupMode), mockito)
TERASOLUNA Server Framework for Java (5.x) Development Guideline
サンプルソースはこちら
(これのMyBatis3を使用したパターンで作成してます。)
3-2.Controllerテスト Junit4, spring-testライブラリ、mockitoによるモック化を使用したパターン
controllerクラスのテストです。
Serviceクラスのメソッドをmockitoライブラリを用いてモック化しています。
今回も、MockMVCはStandaloneSetupのパターンで実装します。
【pom.xml】
Junit、spring-test、mockitoライブラリが必要です。
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> </dependencies>
【テスト対象クラス】
TodoController.java
テスト対象はfinishメソッド
@Controller @RequestMapping("todo") public class TodoController { @Inject TodoService todoService; @Inject Mapper beanMapper; @ModelAttribute public TodoForm setUpForm() { TodoForm form = new TodoForm(); return form; } @RequestMapping(value = "finish", method = RequestMethod.POST) public String finish(@Validated({Default.class}) TodoForm form, BindingResult bindingResult, Model model, RedirectAttributes attributes) { if(bindingResult.hasErrors()) { return list(model); } try { todoService.finish(form.getTodoId()); }catch (BusinessException e) { // TODO: handle exception model.addAttribute(e.getResultMessages()); return list(model); } attributes.addFlashAttribute(ResultMessages.success().add(ResultMessage.fromText("Finished successfully!"))); return "redirect:/todo/list"; } }
(対象メソッドの処理の部分だけ抜粋してます。)
【テストクラス】
TodoControllerTestVerStandaloneMockito.java
public class TodoControllerTestVerStandaloneMockito { @Rule public MockitoRule mockito = MockitoJUnit.rule(); @InjectMocks TodoController target; @Mock TodoService todoService; MockMvc mockMvc; @Before public void setUp() { //standaloneモードでmockMvcを起動 mockMvc = MockMvcBuilders.standaloneSetup(target).build(); } //正常動作のパターン @Test public void testFinish() throws Exception { //mockを作成(getTodoTrueDataメソッドでモック用のデータを返している) when(todoService.finish(anyString())).thenReturn(getTodoTrueData()); //Controllerに投げるリクエストを作成 MockHttpServletRequestBuilder getRequest = MockMvcRequestBuilders.post("/todo/finish") .param("todoId", "cceae402-c5b1-440f-bae2-7bee19dc17fb") .param("todoTitle", "one"); //Controllerにリクエストを投げる(リクエストからfinishメソッドを起動させる。) ResultActions results = mockMvc.perform(getRequest); //結果検証 results.andDo(print()); results.andExpect(status().isFound()); results.andExpect(view().name("redirect:/todo/list")); //FlashMapのデータを取得(model.addFlashAttributeに設定したmessageオブジェクトのtextを取得する。半ば強引) FlashMap flashMap = results.andReturn().getFlashMap(); Collection<Object> collection = flashMap.values(); for(Object obj : collection) { ResultMessages messages = (ResultMessages) obj; ResultMessage message = messages.getList().get(0); String text = message.getText(); assertEquals("Finished successfully!", text); } } //serviceメソッドが異常を返した場合 @Test public void testFinishThrowException() throws Exception { //mockを作成(exceptionを返す) ResultMessages messages = ResultMessages.error(); messages.add(ResultMessage.fromText("[E004]The requested Todo is not found. (id=cceae402-c5b1-440f-bae2-7bee19dc17fb)")); //mockを作成 when(todoService.finish(anyString())).thenThrow(new BusinessException(messages)); //Controllerに投げるリクエストを作成 MockHttpServletRequestBuilder getRequest = MockMvcRequestBuilders.post("/todo/finish") .param("todoId", "cceae402-c5b1-440f-bae2-7bee19dc17fb") .param("todoTitle", "one"); //Controllerにリクエストを投げる(リクエストからfinishメソッドを起動させる。) ResultActions results = mockMvc.perform(getRequest); //結果検証 results.andDo(print()); results.andExpect(status().isOk()); results.andExpect(view().name("todo/list")); //model Confirmation ModelAndView mav = results.andReturn().getModelAndView(); //結果検証 ResultMessages actResultMessages = (ResultMessages)mav.getModel().get("resultMessages"); ResultMessage actResultMessage = actResultMessages.getList().get(0); String text = actResultMessage.getText(); assertEquals("[E004]The requested Todo is not found. (id=cceae402-c5b1-440f-bae2-7bee19dc17fb)", text); } }
内容は3-1の実装内容と変わってません。
ポイントとしては、mockitoライブラリのwhen()メソッドで正常、異常パターンで返してる時の形式が違うということくらいですかね。
thenThrow()メソッドでExceptionを返すことができます。
【その他設定】
特になし
やっぱりmockitoのいいところはテストクラス上でモックの設定もできるということですね~
モッククラスをわざわざ作らなくてもよくなりますし。テストクラスのパターンが増えていくつもファイルが出来たときも管理が楽そうです。
サンプルソースはgithubで公開してます。
Spring Unit Test pattern12
コメントを書く