Formのバリデーションをテストするテストコードを書いていきます。
Spring MVCではクライアントからの入力値をFormクラスにbindすることができます。
bindした値をもとに必須チェック等をFormクラス記載できます。
そのチェック内容のテストとなります。
Controllerクラスのテストコードについては下記の記事でも記載しております。
こちらにいろいろなControllerクラスのテストを記載しているので、参考にしてみてください。
テストコード
概要
ControllerクラスのテストにはMockMvcを利用します。
MockMvcとは、Spring MVCの動作を再現することができて、Controllerテストの際に使われたりするものです。
テストコードの中でFormの値を設定することが可能で、値によってエラーがあるのかないのかという検証を行います。
※今回はFormのバリデーション検証のためのコードしか記載しないので、Modelの検証等は行いません。
Formクラス
Formの内容は以下とします。
Nullを許容しない「@NotNull」
サイズをチェックする「@Size」を指定しています。
package diary.form;
import java.util.Date;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class PostForm {
private int id;
private String categoryForm;
@NotNull (message = "日付を入力してください。")
private Date dateForm;
@NotNull (message = "題名を入力してください。")
@Size(min = 1, max = 25, message="25文字以内で入力してください。")
private String titleForm;
private String contentForm;
public String getCategoryForm() {
return categoryForm;
}
public void setCategoryForm(String categoryForm) {
this.categoryForm = categoryForm;
}
public Date getDateForm() {
return dateForm;
}
public void setDateForm(Date dateForm) {
this.dateForm = dateForm;
}
public String getTitleForm() {
return titleForm;
}
public void setTitleForm(String titleForm) {
this.titleForm = titleForm;
}
public String getContentForm() {
return contentForm;
}
public void setContentForm(String contentForm) {
this.contentForm = contentForm;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Controllerクラス
Controllerの対象メソッドは以下とします。
/**
* 日記を新規登録
* @param postForm
* @param model
* @return
*/
@PostMapping(path="/insert", params="insert")
public String insert(
@Valid @ModelAttribute PostForm form,
BindingResult result,
Model model
) {
if(result.hasErrors()) {
model.addAttribute("error", "パラメータエラーが発生しました。");
return "form";
}
int count = diaryservice.insert(form);
model.addAttribute("postForm", form);
return "redirect:/diary";
}
テストクラス
テストクラスを実装していきます。
package diary;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import java.util.Date;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.validation.BindingResult;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import diary.controller.DiaryController;
import diary.form.PostForm;
@SpringBootTest
@ActiveProfiles("unit")
public class FormTest {
private MockMvc mockMvc;
@Autowired
private FilterChainProxy springSecurityFilterChain;
@Autowired
DiaryController target;
@BeforeEach
public void setup() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setSuffix(".html");
mockMvc = MockMvcBuilders.standaloneSetup(target).apply(springSecurity(springSecurityFilterChain)).setViewResolvers(viewResolver).build();
}
@Test
@WithMockUser
public void 登録() throws Exception {
// パラメータ設定
PostForm form = new PostForm();
form.setCategoryForm("1");
form.setTitleForm("題名");
form.setContentForm("概要");
form.setDateForm(new Date());
// 実行
mockMvc.perform(post("/diary/insert")
.param("insert", "insert")
.flashAttr("postForm", form)
.with(csrf()))
// 検証
// modelの検証
// modelのいずれかにエラーが存在しないこと
.andExpect(model().hasNoErrors())
// postFormにエラーが存在しないこと
.andExpect(model().attributeHasNoErrors("postForm"));
}
@Test
@WithMockUser
public void 必須エラー() throws Exception {
// パラメータ設定
PostForm form = new PostForm();
form.setCategoryForm("1");
form.setContentForm("概要");
form.setDateForm(new Date());
// 実行
ResultActions results = mockMvc.perform(post("/diary/insert")
.param("insert", "insert")
.flashAttr("postForm", form)
.with(csrf()))
// 検証
// modelのいずれかにエラーがあること
.andExpect(model().hasErrors())
// postFormにエラーが存在すること
.andExpect(model().attributeHasErrors("postForm"));
BindingResult bindResult = (BindingResult) results.andReturn().getModelAndView().getModel().get(BindingResult.MODEL_KEY_PREFIX + "postForm");
String mes = bindResult.getFieldError().getDefaultMessage();
// メッセージ検証
assertEquals("題名を入力してください。", mes);
}
@Test
@WithMockUser
public void サイズエラー() throws Exception {
// パラメータ設定
PostForm form = new PostForm();
form.setCategoryForm("1");
form.setTitleForm("12345678901234567890123456");
form.setContentForm("概要");
form.setDateForm(new Date());
// 実行
ResultActions results = mockMvc.perform(post("/diary/insert")
.param("insert", "insert")
.flashAttr("postForm", form)
.with(csrf()))
// 検証
// modelのいずれかにエラーがあること
.andExpect(model().hasErrors())
// postFormにエラーが存在すること
.andExpect(model().attributeHasErrors("postForm"));
BindingResult bindResult = (BindingResult) results.andReturn().getModelAndView().getModel().get(BindingResult.MODEL_KEY_PREFIX + "postForm");
String mes = bindResult.getFieldError().getDefaultMessage();
assertEquals("25文字以内で入力してください。", mes);
}
}
3つのメソッドを作成しています。
・Formがエラーにならない
・NotNullチェックのエラーになる
・Sizeチェックのエラーになる
テストをしてみると問題なく検証できていることが確認できます。
参考文献
ModelResultMatchers (Spring Framework 6.0.11 API)
declaration: package: org.springframework.test.web.servlet.result, class: ModelResultMatchers