2013-04-26 72 views
4

我试图测试下面的Spring MVC控制器的方法:测试一个Spring MVC控制器的方法和春天MockMvc *类

@RequestMapping(value = "/preferences/email", method = RequestMethod.POST, produces = "text/html") 
public String modifyEmail(@ModelAttribute @Validated({ Validation.EmailModification.class }) EmailInfo emailInfo, BindingResult bindingResult, Model model, Locale locale) { 
    Member member = memberService.retrieveCurrentMember(); 
    if (!preferencesService.isEmailAvailable(emailInfo.getEmail())) { 
     if (member.getEmail().equals(emailInfo.getEmail())) { 
      bindingResult.addError(new FieldError("emailInfo", "email", messageSource.getMessage("controller.preferences.same_email", null, locale))); 
     } else { 
      bindingResult.addError(new FieldError("emailInfo", "email", messageSource.getMessage("controller.preferences.email_already_used", null, locale))); 
     } 
    } 
    if (bindingResult.hasErrors()) { 
     model.addAttribute("emailInfo", emailInfo); 
     return "preferences"; 
    } 
    preferencesService.modifyEmail(member, emailInfo.getEmail()); 
    return "redirect:/preferences/email"; 
} 

这里是EmailInfo豆:

@RooEquals 
@RooJavaBean 
public class EmailInfo { 

    @NotNull(groups = { Validation.EmailModification.class }) 
    @Pattern(regexp = "^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)+$", groups = { Validation.EmailModification.class }) 
    private String email; 

    private boolean activated; 

    private String token; 
} 

下面是测试等级:

@ContextConfiguration 
@WebAppConfiguration 
@RunWith(SpringJUnit4ClassRunner.class) 
public class PreferenceControllerTest { 

    @Autowired 
    private WebApplicationContext ctx; 

    private MockMvc mockMvc; 

    @Autowired 
    private MemberService memberService; 

    @Autowired 
    private PreferencesService preferencesService; 

    @Autowired 
    private MemberRepository memberRepository; 

    @Autowired 
    private SigninService signinService; 

    @Autowired 
    private MessageSource messageSource; 

    @Before 
    public void setup() { 
     mockMvc = webAppContextSetup(ctx).build(); 
     Member currentMember = new Member(); 
     currentMember.setEmail("[email protected]"); 
     when(memberService.retrieveCurrentMember()).thenReturn(currentMember); 
     when(preferencesService.isEmailAvailable("[email protected]")).thenReturn(Boolean.FALSE); 
    } 

    @Test 
    public void test() throws Exception { 
     mockMvc.perform(post("/preferences/email")// 
       .param("email", "[email protected]"))// 
       .andDo(print()).andExpect(model().attributeHasNoErrors("emailInfo", "email")); 
    } 

    @Configuration 
    public static class testConfiguration { 
     @Bean 
     public PreferenceController preferenceController() { 
      return new PreferenceController(); 
     } 

     @Bean 
     public PreferencesService preferenceService() { 
      return mock(PreferencesService.class); 
     } 

     @Bean 
     public MemberService memberService() { 
      return mock(MemberService.class); 
     } 

     @Bean 
     public MemberRepository memberRepository() { 
      return mock(MemberRepository.class); 
     } 

     @Bean 
     public SigninService signinService() { 
      return mock(SigninService.class); 
     } 

     @Bean 
     public MessageSource messageSource() { 
      return mock(MessageSource.class); 
     } 

    } 
} 

奇怪的是,我得到以下输出:

MockHttpServletRequest: 
     HTTP Method = POST 
     Request URI = /preferences/email 
      Parameters = {email=[[email protected]]} 
      Headers = {} 

      Handler: 
       Type = com.bignibou.controller.PreferenceController 

       Async: 
    Was async started = false 
     Async result = null 

    Resolved Exception: 
       Type = null 

     ModelAndView: 
      View name = preferences 
       View = null 
      Attribute = emailInfo 
       value = [email protected] 
       errors = [Field error in object 'emailInfo' on field 'email': rejected value [null]; codes []; arguments []; default message [null]] 

      FlashMap: 

MockHttpServletResponse: 
       Status = 200 
     Error message = null 
      Headers = {} 
     Content type = null 
       Body = 
     Forwarded URL = preferences 
     Redirected URL = null 
      Cookies = [] 

测试失败,上面的输出,我不知道为什么。我期望测试通过,因为电子邮件地址可用。

任何人都可以请帮忙吗?

编辑1

下不工作之一:

@Before 
    public void setup() { 
     mockMvc = webAppContextSetup(ctx).build(); 
     Member currentMember = new Member(); 
     currentMember.setEmail("[email protected]"); 
     when(memberService.retrieveCurrentMember()).thenReturn(currentMember); 
     when(preferencesService.isEmailAvailable(eq("[email protected]"))).thenReturn(Boolean.FALSE); 
     when(preferencesService.isEmailAvailable(eq("[email protected]"))).thenReturn(Boolean.TRUE); 
    } 

编辑2

我能得到与上述编辑1工作加上下面的测试:

@Test 
    public void test() throws Exception { 
     mockMvc.perform(post("/preferences/email")// 
       .param("email", "[email protected]"))// 
       .andDo(print())// 
       .andExpect(model().attributeHasNoErrors("emailInfo")); 
    } 

回答

1

Updae回答评论。

在控制器尝试

String email=emailInfo.getEmail(); if(!preferencesService.isEmailAvailable(email))){而不是if (!preferencesService.isEmailAvailable(emailInfo.getEmail())) {

不知道,只是一个可能的解决方案

或者尝试

when(preferencesService.isEmailAvailable(eq("[email protected]"))).thenReturn(Boolean.TRUE); 
when(preferencesService.isEmailAvailable(eq("[email protected]"))).thenReturn(Boolean.FALSE); 

阂您使用的Mockito实现嘲讽?


我不是100%确定,但这里是我如何理解你的代码。

when(preferencesService.isEmailAvailable("[email protected]")).thenReturn(Boolean.FALSE); 

如果preferencesService.isEmailAvailable返回true,那么你在用力mock exercise

所以返回falsemock exercisepreferencesService.isEmailAvailable总是返回false

现在,在您Controller

if (!preferencesService.isEmailAvailable(emailInfo.getEmail())) { 
     if (member.getEmail().equals(emailInfo.getEmail())) { 
      bindingResult.addError(new FieldError("emailInfo", "email", messageSource.getMessage("controller.preferences.same_email", null, locale))); 
     } else { 
      bindingResult.addError(new FieldError("emailInfo", "email", messageSource.getMessage("controller.preferences.email_already_used", null, locale))); 
     } 
    } 

如果preferencesService.isEmailAvailablefalse然后!使其true这样的代码会一直往里走if块,你会得到Field Error,因此Test fails

+0

但它不应该进去,因为我不是实际调用与[email protected] ... – balteo 2013-04-26 16:12:38

2

有了这个:

.param("email", "[email protected]"))// 

您请求参数设置为字符串值。但是,您尚未显示从String到EmailInfo的转换。

在您的测试要检查emailInfo领域称为电子邮件。

我不知道这是什么呢?

when(preferencesService.isEmailAvailable("[email protected]")).thenReturn(Boolean.FALSE); 

什么是应该做的,你已经注入了你的preferenceService使用autowired。

+0

喜的参数的方法!我想指定何时使用[email protected]参数调用isEmailAvailable,那么它应该返回false。从String到EmailInfo的转换是什么意思? – balteo 2013-04-26 16:09:27

+1

@balteo您的控制器方法需要EmailInfo类型的参数emailInfo,但是您的测试会提交一个带名称电子邮件的字符串。 – NimChimpsky 2013-04-26 16:19:30

+0

但我只能通过字符串可以吗?有没有办法传入一个对象/ bean?顺便说一句,我确实尝试'.param(“emailInfo.email”,“[email protected]”))'无济于事...... – balteo 2013-04-26 16:29:53

相关问题