MockMvcテストでリクエストパラメータを送る際の「param」と「flashAttr」の違い

# この記事の内容について
　SpringBootでコントローラのテストをMockMVCで行うとき、リクエストパラメータを送る際に使う「param」と「flashAttr」の違いについて、自分なりにまとめました。
　私はまだエンジニア歴1年未満の初学者なので、間違い等があればご指摘いただけると幸いです。

# paramとflashAttrの違い
### 以下の6パターンをチェックしました。
#### paramを使った場合
1. param("変数名", "具体的な値") → 成功
1. param("変数名", "具体値を格納した変数") → 失敗(テスト失敗)
1. param("変数名", "インスタンス") → 失敗(値がNULL)
### flashAttrを使った場合
1. flashAttr("変数名",　"具体的な値") → 失敗(値がNULL)
1. flashAttr("変数名", "具体値を格納した変数") → 失敗(値がNULL)
1. flashAttr("変数名", "インスタンス") → 成功
### 結論
#### paramを使う場合
→ param("変数名", "具体的な値")
#### flashAttrを使う場合
→ flashAttr("変数名", "インスタンス")

# 具体的な検証内容
```java: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:/";
}
```

```java:Profile
@Data
public class Profile {

	private String name;
	private Integer age;

}
```

```java:検証用の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)

}

```