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

时间:2017-02-24 19:17:59

标签: java spring-boot spring-data mockito spring-mvc-test

所以我使用带有JPA和Spring MVC的Spring Data用Spring Boot编写这个Web应用程序,我想进行模拟控制器测试。我想出了如何测试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. 我的服务在db中保留成员JPA实体(如果没有错误)
  3. 方法将我重定向到索引页
  4. 这是我(差)测试类到目前为止的样子:

    @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")));
    
        }
    }
    
    据我所知,春季靴子使用Mockito。我对EasyMock有一些经验,但我想尽可能使用弹簧默认值。有人能说明如何实现这个目标吗?

1 个答案:

答案 0 :(得分:1)

我认为应该和不应该嘲笑的内容有点混乱。

如果我正确地阅读了您的问题,您实际上是在尝试对[XmlRoot(ElementName = "Step")] public class WorkflowStep { [XmlAnyElement("Action")] public XmlElement[] Actions { get; set; } } 进行单元测试。因此,您很可能不应该模拟该类,但实际上是测试该类。

我相信您会创建RegisterMemberController的{​​{3}} / fakes / dummies / stubs / mocks,{{1} }和MemberService类。

这些类将由您的单元测试创​​建并在测试期间交给您的控制器,这将强制测试您有兴趣证明/反驳的逻辑。

仅供参考,在验证调用RegisterMemberBean类时,您将使用模拟。其余类可以是假人或存根。

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