spring mvc 如何测试我的服务在 post 请求中持久化实体

spring mvc how to test that my service persists entities in post request

所以我正在编写这个 Web 应用程序 Spring Boot using Spring Data with JPA and Spring MVC 我想进行模拟控制器测试。我想出了如何测试 get 方法,但在我的控制器 post 方法中,一个新的 JPA 实体正在使用我的服务进行持久化或更新。这是我的控制器的样子:

@Controller
@RequestMapping("/registerMember")
public class RegisterMemberController {

    @Autowired
    private MemberService memberService;

    @GetMapping
    public String index(RegisterMemberBean registerMemberBean) {
        return "registerMember";
    }

    @PostMapping
    public String handleSubmit(@Valid RegisterMemberBean registerMemberBean, BindingResult bindingResult, Model model) {
        Member member = registerMemberBean.getMember();
        boolean isRepeatPasswordCorrect = !isRepeatPasswordIncorrect(member.getPassword(), registerMemberBean.getComparePassword());

        if(isAnyErrors(isRepeatPasswordCorrect, !bindingResult.hasErrors())) {
            if(!isRepeatPasswordCorrect) {
                model.addAttribute("isRepeatPasswordIncorrect", true).
                addAttribute("isRepeatPasswordIncorrectMsg", "Passwords don't match");
            }
            return "registerMember";
        }

        boolean errUsername = !memberService.isNoOtherEntityWithUserName(0, member.getUserName());
        boolean errEmail = !memberService.isNoOtherEntityWithEmail(0, member.getEmail());

        if(errUsername || errEmail) {
            if(errUsername) {
                model.addAttribute("isExistingUserName", true).addAttribute("isExistingUserNameMsg", "Already a user with that username");
            } if(errEmail) {
                model.addAttribute("isExistingEmail", true).addAttribute("isExistingEmailMsg", "Already a user with that email");
            }
            return "registerMember";
        }

        getMainService().save(member);
        return redirectTo("index", new RedirectEntity("member", member.getId()));
    }


}

现在在我的模拟控制器测试中,我想确保我的 post 方法执行以下操作:

  1. 如果 BindingResults 有任何错误,请重新加载页面
  2. 我的服务将成员 JPA 实体保存在数据库中(如果没有错误)
  3. 方法将我重定向到索引页面

这是我的(糟糕的)测试 class 到目前为止的样子:

@RunWith(SpringRunner.class)
@TestPropertySource(locations="classpath:application_test.properties")
@WebAppConfiguration
public class RegisterMemberControllerTest {

    private MockMvc mockMvc;

    @MockBean
    private MemberService memberService;

    @MockBean
    private RegisterMemberController controller;

    @Before
    public void init() {
        mockMvc = MockMvcBuilders.standaloneSetup(controller).setViewResolvers(new StandaloneMvcTestViewResolver()).build();
        controller.setMainService(memberService);
    }

    @Test
    public void testIndex() throws Exception {
        mockMvc.perform(get("/registerMember"))
         .andExpect(status().isOk())
         .andExpect(forwardedUrl("registerMember");
    }

    @Test
    public void testHandleSubmit() throws Exception {
        RegisterMemberBean registerMemberBean = new RegisterMemberBean();
        registerMemberBean.setMember(TestFixture.getValidMemberWithoutReferences());

        Member member = TestFixture.getValidMember();

        mockMvc.perform(post(Page.REGISTER_MEMBER)).andExpect(status().isOk());
        when(mockMvc.perform(post(Page.REGISTER_MEMBER)).andExpect((ResultMatcher) memberService.save(member)).andExpect(forwardedUrl("redirect:/index/member=" + member.getId() + ".html")));

    }
}

据我了解 spring 引导使用 Mockito。我对 EasyMock 有一些经验,但我想尽可能多地使用 spring 默认值。有人可以展示如何实现这一目标吗?

我认为对于什么应该嘲笑什么不应该嘲笑有点混乱。

如果我没看错你的问题,你实际上是在尝试对 RegisterMemberController 进行单元测试。因此,您很可能不应该模拟 class,而应该实际测试 class.

我相信您会创建 fakes/dummies/stubs/mocks/spies 您的 MemberServiceRegisterMemberBeanBindingResult classes.

这些 class 将由您的单元测试创​​建并在测试期间交给您的控制器,这将强制测试您感兴趣的逻辑 proving/disproving。

仅供参考,在验证 MemberService class 被调用时,您将在此处使用模拟。 classes 的其余部分可以是假人或存根。

旁注:我建议从 handleSubmit() 方法中删除 Model 参数,因为它似乎没有在任何地方使用。