SpringMVCでテストを書く

最近会社のJavaプロジェクトで新しく使うフレームワークとして、どれを推奨すべきか検討しています。
で個人的には、今のところ「SpringMVC」かなと思っています。

今は社内の方に紹介するためにサンプルを作成してナレッジを蓄積しているところなんですが、テストの書き方について覚え書きをしておこうと思います。

いきなりですが、テストコードのサンプルから。

package jp.co.sample;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml" })
public class HomeControllerTest {
	@Autowired
	private WebApplicationContext wac;

	private MockMvc mockMvc;

	@Before
	public void setup() {
		mockMvc = webAppContextSetup(wac).build();
	}

	@Test
	public void Homeコントローラのhomeメソッドの検証() throws Exception {
		mockMvc.perform(get("/sample/home")).andExpect(status().isOk()).andExpect(view().name("home"))
				.andExpect(model().hasNoErrors());
	}

	@Test
	public void PointコントローラのindexメソッドへPOST() throws Exception {
//		mockMvc.perform(post("/sample/point")).andExpect(status().isMethodNotAllowed())
		MvcResult mvcResult = mockMvc.perform(post("/sample/point").param("point", "100"))
				                     .andExpect(status().isOk())
				                     .andExpect(view().name("point")).andReturn();
		ModelMap modelMap = mvcResult.getModelAndView().getModelMap();
	    Object object = modelMap.get("point");
	    assertThat(object, is(not(nullValue())));
	    assertThat(object, is(instanceOf(Integer.class)));

	}
}

performメソッドで遷移する画面のURLパターンを指定します。最初のテストでは「/sample/home」をgetで呼び出した時のテストです。
まずはステータスをチェックしています。続いてcontroller側の処理が終わって画面遷移する時の遷移先のチェックです。
最初のテストでは"home"を返すかチェックしています。

@Controller
@RequestMapping("/sample")
public class HomeController {

	@RequestMapping
	public String index(Model model) {
		return home(model);
	}

	@RequestMapping(value = "home", method = RequestMethod.GET)
	public String home(Model model) {
		model.addAttribute(new HomeForm());
		Date date = new Date();
		model.addAttribute("date", date);

		UserDao dao = new UserDao();
		List<User> list = dao.all();
		model.addAttribute("userList", list);
		return "home";
	}
	@RequestMapping(value = "skip", method = RequestMethod.GET)
	public String skip(Model model) {
		System.out.println("SKIP ACTION");
		return "redirect:home";
	}	
}

performメソッドはコントローラに対する処理を行います。引数にはRequestBuilderインタフェースの実装をセットします。RequestBuilderインターフェースには、HTTP Methodによってそれぞれgetやpost以外にもdeleteやputもあります。
performメソッドはResultActionインタフェース型のオブジェクトを返します。
そしてandExpectメソッドを使ってレスポンスのステータスや遷移先のチェック、requestの中のチェックなどを行います。
(12/5 追記しました。)

またリクエストの中身や例外のチェックなどもできます。こちらも順次追記していきます。