【メモ/未解決】Spring BootでMockMvcのレスポンスボディが空文字になる。

Spring Bootを始めたばかりなのですが、よくわからんことがあったのでメモ。解決していません。私がSpring BootのDIよくわかってないだけだと思う。

あらまし

ServiceをモックせずにControllerのユニットテスト(JUnit4)を実行したらMockMVCのレスポンスボディが空になってしまった。対象のSpring Bootのバージョンは1.5系で、テンプレートエンジンはThymeleafを使用。

テスト対象のController

@Controller
@RequestMapping("/")
public class DemoController {

  @Autowired
  DemoService service;
  
  @GetMapping("hello")
  public String demo (Model model) {
    model.addAttribute("message", service.getMessage());
    return "hello";
  }

}

Service

@Service
public class DemoService {
  public String getMessage() {
    return "message.";
  }
}

失敗するテスト

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoControllerTests {

  @Autowired
  private DemoController controller;

  private MockMvc mockMvc;

  @Before
  public void setup() {
     mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
  }

  @Test
  public void helloにアクセスする() throws Exception {
    mockMvc.perform(get("/hello"))
      .andExpect(status().isOk()) // ここは通る
      .andExpect(content().string(containsString("message"))); // contentが空文字になってしまって通らない
  } // 実際のアプリケーションで /hello にアクセスすると期待通りの挙動になる

}

ViewResolver?が動いてないっぽい?ControllerだけインジェクトしてもViewResolver?までインジェクトできないのかもしれない。
ServiceがMockBeanでいいならGetting Started · Testing the Web Layer通りに書けばいいが、今回はMockを使わずに通しの動作をテストしたい。

回避策として書いて、かつ期待通りには動作したテスト

とりあえずWebApplicationContextをAutowiredでインジェクトしてみたら動いた。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoControllerTests {

  @Autowired
  private WebApplicationContext wac;

  private MockMvc mockMvc;

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

  @Test
  public void helloにアクセスする() throws Exception {
    mockMvc.perform(get("/hello"))
      .andExpect(status().isOk())
      .andExpect(content().string(containsString("message"))); // 期待通り通った
  }

}

※動かないパターンのレスポンスボディが空文字になる理由が理解できてないので、このコードはあくまで回避策。