この記事の内容について
SpringBootでコントローラのテストをMockMVCで行うとき、リクエストパラメータを送る際に使う「param」と「flashAttr」の違いについて、自分なりにまとめました。
私はまだエンジニア歴1年未満の初学者なので、間違い等があればご指摘いただけると幸いです。
paramとflashAttrの違い
以下の6パターンをチェックしました。
paramを使った場合
- param("変数名", "具体的な値") → 成功
- param("変数名", "具体値を格納した変数") → 失敗(テスト失敗)
- param("変数名", "インスタンス") → 失敗(値がNULL)
flashAttrを使った場合
- flashAttr("変数名", "具体的な値") → 失敗(値がNULL)
- flashAttr("変数名", "具体値を格納した変数") → 失敗(値がNULL)
- flashAttr("変数名", "インスタンス") → 成功
結論
paramを使う場合
→ param("変数名", "具体的な値")
flashAttrを使う場合
→ flashAttr("変数名", "インスタンス")
具体的な検証内容
HelloController
@GetMapping("/")
public String hello(@ModelAttribute Profile profile) {
return "hello";
}
/** 引数にオブジェクトを渡す */
@PostMapping("/test1")
public String greet(@ModelAttribute Profile profile,
RedirectAttributes redirectAttributes) {
System.out.println("test1");
System.out.println(profile);
redirectAttributes.addFlashAttribute("name", profile.getName());
redirectAttributes.addFlashAttribute("age", profile.getAge());
return "redirect:/";
}
/** 引数に変数を渡す */
@PostMapping("/test2")
public String greet(String name, Integer age,
RedirectAttributes redirectAttributes) {
System.out.println("test2");
System.out.println("name=" + name + ", age=" + age);
redirectAttributes.addFlashAttribute("name", name);
redirectAttributes.addFlashAttribute("age", age);
return "redirect:/";
}
Profile
@Data
public class Profile {
private String name;
private Integer age;
}
検証用のmockMvcテスト
@SpringBootTest
@AutoConfigureMockMvc
class HelloControllerTest {
@Autowired
private MockMvc mockMvc;
/** paramを使ったテスト */
@Test
void test1() throws Exception {
// 実行&検証
mockMvc.perform(post("/test2")
.param("name", "Taro")
.param("age", "20"))
.andExpect(redirectedUrl("/"))
.andExpect(status().isFound());
}
// 出力結果:name=Taro, age=20
@Test
void test2() throws Exception {
// 準備
var name = "Taro";
var age = 20;
// 実行&検証
mockMvc.perform(post("/test2")
// おそろく、ここで「name」と「age」が呼び出されない。
.param("name", "name")
.param("age", "age"))
.andExpect(redirectedUrl("/"))
.andExpect(status().isFound());
}
// テストが失敗する
@Test
void test3() throws Exception {
// 準備
var profile = new Profile();
profile.setName("Taro");
profile.setAge(20);
// 実行&検証
mockMvc.perform(post("/test1")
.param("profile", "profile"))
.andExpect(redirectedUrl("/"))
.andExpect(status().isFound());
}
// 出力結果:profile(name=null, age=null)
/** flashAttrを使ったテスト */
@Test
void test4() throws Exception {
// 実行&検証
mockMvc.perform(post("/test2")
.flashAttr("name", "Taro")
.flashAttr("age", 20))
.andExpect(redirectedUrl("/"))
.andExpect(status().isFound());
}
// 出力結果:name=null, age=null
@Test
void test5() throws Exception {
// 準備
var name = "Taro";
var age = 20;
// 実行&検証
mockMvc.perform(post("/test2")
.flashAttr("name", name)
.flashAttr("age", age))
.andExpect(redirectedUrl("/"))
.andExpect(status().isFound());
}
// 出力結果:name=null, age=null
@Test
void test6() throws Exception {
// 準備
var profile = new Profile();
profile.setName("Taro");
profile.setAge(20);
// 実行&検証
mockMvc.perform(post("/test1")
.flashAttr("profile", profile))
.andExpect(redirectedUrl("/"))
.andExpect(status().isFound());
}
// 出力結果:profile(name=Taro, age=20)
}