java - spring mvc 如何测试我的服务是否在发布请求中保留实体

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

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

@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()));
    }


}

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

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

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

@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 Boot 使用 Mockito。我对 EasyMock 有一些经验,但我想尽可能使用 spring 默认值。有人可以展示如何实现这一目标吗?

最佳答案

我认为对于什么应该被 mock 、什么不应该被 mock 存在一些困惑。

如果我正确地阅读了您的问题,您实际上是在尝试对您的 RegisterMemberController 进行单元测试。因此,您很可能不应该模拟该类,而应该实际测试该类。

我相信您会创建 fakes/dummies/stubs/mocks/spies您的 MemberServiceRegisterMemberBeanBindingResult 类。

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

仅供引用,当验证 MemberService 类被调用时,您将在此处使用模拟。其余的类可以是虚拟类或 stub 类。

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

关于java - spring mvc 如何测试我的服务是否在发布请求中保留实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42446610/

相关文章:

Spring Data MongoDB 与 Java 8 LocalDate MappingException

google-app-engine - 在 Google Appengine 上使用 Spring Data JPA

java - 小程序中的netty抛出AccessControlException

java - CData JDBC 驱动程序 | java.lang.Exception : Could not find web browser

java - 如何动态更改 application.properties 中的参数,以便可以使用新值来触发计划作业

java - Spring 启动: Count Page Views - Actuators

java - 为什么 String.length() 是一种方法?

java - Firestore Recycler 未在应用屏幕上显示任何结果且没有错误

java - 在 Spring Boot 中读取环境变量

mongodb - Spring Data MongoDB - 聚合框架 - 组操作中的无效引用