SpringMVC Cotrollerのテスト | Hello, Stupid World!

Hello, Stupid World!

いろいろとメモ代わりに書いていきます。

Webシステムで困りがちなのがControllerの自動テストです。

リクエストを受けて正常にControllerのメソッドが動作するか、
テストするのが難しいところです。
(メソッドが正常に動くかではなくメソッドが正常に呼ばれるかという結合テスト)

SpringMVCには、そんな時に便利なSpringMVC Testがあります。
まず使うにはspring-testが必要なのでpom.xmlに以下を追加します。

[pom.xml]
<dependency> 
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>${org.springframework-version}</version>
  <scope>test</scope>
</dependency>

この時、versionには注意して下さい。
他のspringframeworkとversionが異なる場合、正常に動作しません。
少しハマリました・・・

で、テストコードはこんな感じ

[UserControllerTest.java]
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml" })
public class UserControllerTest {
  @Autowired
  private WebApplicationContext wac;

  private MockMvc mockMvc;

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

  @Test
  public void testInput() throws Exception {
    mockMvc.perform(get("/")).andExpect(status().isOk())
      .andExpect(view().name("user/input"))
      andExpect(model().hasNoErrors());
  }
  @Test
  public void testShow() throws Exception {
    mockMvc.perform(post("/").param("name",""))
      .andExpect(status().isOk())
      .andExpect(view().name("user/input"))
      .andExpect(model().hasErrors());
    mockMvc.perform(post("/").param("name","1234567"))
      .andExpect(status().isOk())
      .andExpect(view().name("user/input"))
      .andExpect(model().hasErrors());

    mockMvc.perform(post("/").param("name","Trap"))
      .andExpect(status().isOk())
      .andExpect(view().name("user/show"))
      .andExpect(model().hasNoErrors());
  }
}

上のRunWith、WebAppConfiguration、ContextConfigurationは
必須です。
その後、DIでWebApplicationContextにインジェクションしてbuildメソッド
でMockMvcクラスを取得します。
ここまでが準備。

使い方は見てのとおりですが、performでリクエストを投げ
andExpectで条件と合致するか判定します。

performの引数はgetメソッドやpostメソッドです。
(それぞれGETリクエスト、POSTリクエストに相当)
get("/")ならばコンテキストルートへGETリクエストを
飛ばします。
パラメータをつける場合はparamメソッドで。

andExpectの引数は上記以外にも多くあります。
statusはレスポンスステータス
view.nameならばビューの名前
model.hasErrorsならばバリデータでエラーがあるか
を判定できます。

参考にControllerとmodelを。

[InputModel.java]
public class InputModel {
  @NotEmpty
  @Size(max = 6)
  private String name;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

[UserController.java]
@Controller
public class UserController {
  @RequestMapping(method = RequestMethod.GET)
  public ModelAndView input() {
    return new ModelAndView("user/input", "inputModel", new InputModel());
  }
  @RequestMapping(method = RequestMethod.POST)
  public ModelAndView show(@Valid @ModelAttribute("inputModel") InputModel inputModel,
    BindingResult bindingResult, Model model) {
  if (bindingResult.hasErrors()) {
    return new ModelAndView("user/input");
  }
  return new ModelAndView("user/show", "inputModel", inputModel);
}

STSは標準でMaven入ってるので便利ですね。
Maven使うと欲しいライブラリ探してダウンロードしてビルドパスに
加えてという作業が数行書くだけで自動化されるのでカンタン!