目次
- 1. Spring FrameworkのUnitテスト実装方法 3-2.Controllerテスト(Junit4, spring-test, MockMvc(StandaloneSetupMode), mockito)
- 2. 3-2.Controllerテスト Junit4, spring-testライブラリ、mockitoによるモック化を使用したパターン
Spring FrameworkのUnitテスト実装方法 3-2.Controllerテスト(Junit4, spring-test, MockMvc(StandaloneSetupMode), mockito)
【サンプルソース】
TERASOLUNA Server Framework for Java (5.x) Development Guideline
サンプルソースはこちら
(これのMyBatis3を使用したパターンで作成してます。)
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