Spring フラッシュスコープを利用したリダイレクトと単体テスト


あるエンドポイントから別のエンドポイントにリダイレクトさせる際に、フラッシュスコープを利用するとリダイレクト先へパラメータを引き継がせることができる。

コントローラ

以下のコントローラで/fromにGETでアクセスした際に、/toへリダイレクトさせる。
リダイレクト元の処理で、bookNamebuyerListをフラッシュスコープに突っ込んで、リダイレクト先へ引き継がせる。

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.Arrays;
import java.util.List;

@Controller
public class DemoController {

    @GetMapping(path = "/from")
    public String from(RedirectAttributes redirectAttributes) {

        redirectAttributes.addFlashAttribute("bookName", "ドラえもん");

        List<String> buyerList = Arrays.asList("野比", "剛田");
        redirectAttributes.addFlashAttribute("buyerList", buyerList);

        return "redirect:/to";
    }

    @GetMapping(path = "/to")
    public String to(Model model) {
        System.out.println(model);
        return "demo";
    }
}

/fromにアクセスすると/toにリダイレクトされ、引き継がれたパラメータがコンソールに表示される。

{bookName=ドラえもん, buyerList=[野比, 剛田]}

ポイント

  • リダイレクト元のメソッドでRedirectAttributesを引数に設定し、.addFlashAttributeで引き継ぐattribute名と内容を指定する。なお、attribute名を省略することもできるが、その場合はクラス名に応じてattribute名が自動設定される。
  • リダイレクト先では引数に設定したModelの中にattributeが含まれている。内容を参照したい場合は.getAttributeでattribute名を指定する。

単体テスト

/fromにアクセスした際に、パラメータを引き継いで/toへリダイレクトされることを確認する。

package com.example.demo.controller;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import java.util.Arrays;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.flash;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class DemoControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void redirectWithAttributes() throws Exception {
        mockMvc.perform(get("/from"))
                .andExpect(status().isFound())
                .andExpect(redirectedUrl("/to"))
                .andExpect(flash().attribute("bookName", "ドラえもん"))
                .andExpect(flash().attribute("buyerList", Arrays.asList("野比", "剛田")));
    }
}

ポイント

  • andExpect()で期待値通りに動いていることを確認。
  • status().isFound()でHTTPステータスが302であることを確認。
  • redirectedUrl()でリダイレクト先のパスをアサーション。
  • flash().attribute()で引き継ぐパラメータのアサーション。

FlashMapによる取り出し

以下のように引き継ぎパラメータをFlashMapで取り出すことができる。余計なパラメータが入っていないことの確認や、単純な文字列表現ではアサーションできない場合はこちらを利用する。


    @Test
    public void redirectWithAttributes() throws Exception {

        MvcResult mvcResult = mockMvc.perform(get("/from"))
                .andExpect(status().isFound())
                .andExpect(redirectedUrl("/to"))
                .andReturn();

        FlashMap flashMap = mvcResult.getFlashMap();

        assertThat(flashMap.size()).isEqualTo(2);
        assertThat(flashMap.get("bookName")).isEqualTo("ドラえもん");
        assertThat(flashMap.get("buyerList")).isEqualTo(Arrays.asList("野比", "剛田"));