前提・実現したいこと
Springの学習をしています。
コントローラのテストを書きたいのですが、うまくいかずに困っています。
該当のソースコード
コントローラの実装
java
1@Controller 2@RequiredArgsConstructor 3@RequestMapping("/user") 4public class SignupController { 5 6 private final UserService userService; 7 8 private final ModelMapper modelMapper; 9 10 // ・・・ 11 12 @PostMapping("/signup") 13 public String postSignup(Model model, Locale locale, 14 @ModelAttribute @Validated(ValidGroupOrder.class) SignupForm form, 15 BindingResult bindingResult) { 16 if (bindingResult.hasErrors()) { 17 return getSignup(model, locale, form); 18 } 19 20 MUser user = modelMapper.map(form, MUser.class); 21 22 userService.signup(user); 23 24 return "redirect:/login"; 25 } 26}
試したこと
とりあえず以下のテストは通ったのですが、
コントローラが使用する依存関係を全て実行してしまい、
また、データベースも更新してしまうのでテストとしてどうかと考えています。
java
1@WebMvcTest(SignupController.class) 2public class SignupControllerTest { 3 @Autowired 4 MockMvc mockMvc; 5 6 @MockBean 7 UserService userService; 8 @MockBean 9 ModelMapper modelMapper; 10 11 // ・・・ 12 13 @Test 14 void postSignupErrorsTest() throws Exception { 15 SignupForm form = new SignupForm(); 16 17 mockMvc.perform( 18 post("/user/signup") 19 .flashAttr("form", form) 20 ).andExpect(model().hasErrors()); 21 } 22}
依存関係の部分はメソッドをmockしたいのですが、
MUserがローカル変数になっているため、mock化できなくなっています。
実装のコードも含めて、どうしたらいいか教えていただけますでしょうか。
手法はともかく、テストケースはどのように準備されてますか?
何を担保・確認する目的があるテストなのかを決めておかないとテストの意味がないです。
コメントありがとうございます。
掲載しているメソッドはサインアップのコントローラで、
バリデーション失敗or成功の2つのテストケースで条件網羅になると考えています。(バリデーションの詳細はFormクラスのテストで担保したい)
質問としては、バリデーション失敗or成功が見たいのであってDBの操作はこのテストでは担保したくないのですが、mockの仕方がわからないというものでした。
mockしたいとは言っていますが、実はコントローラのテストはDIされるクラスまで含めて動かしてしまうべきものだったりするのでしょうか。
これも含めて、実際どうするのかいいか教えていただけると助かります。
>バリデーション失敗or成功が見たいのであって
このあたりが質問からは見えなかったので、質問修正して追記してもらえればと思います。
強いてなら外部からの引数でフラグで切り替えるとかになるでしょうけど、あまり業務ロジックに直接関係ない情報は持ちたくないというのは分かります。
バリデーションとDB反映の入り口を完全に分けるしかないですね。
あなたの回答
tips
プレビュー