1

我正在使用 MockMvc 和 Mockito,大量使用 Spring温室样本。我有一个简单的控制器,它返回一个字符串视图名,如果出现某种错误,则返回 null。它在 servlet 环境中运行良好,但是当我尝试使用 MockMvc StandaloneSetup 对控制器进行单元测试时,我得到了

javax.servlet.ServletException: Circular view path [register]: would dispatch back to the current handler URL [/register] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)

这是我的控制器

@Controller
public class SignupController {

@RequestMapping(value="/register", method=RequestMethod.GET)
public RegistrationForm createNewRegForm(){
    return new RegistrationForm();
}

/**
 * Process a signup form submission.
 * Delegate to a {@link SignupServiceImpl} to actually complete the signin transaction.
 * Redirects the new member to the application home page on successful sign-in.
 */
@RequestMapping(value="/register", method=RequestMethod.POST)
public String signup(@Validated(Registration.class) RegistrationForm form, BindingResult formBinding) {
    if(formBinding.hasErrors())
        return null;
    boolean success = signupHelper.signup(form.getUser(), formBinding);
    return (!formBinding.hasErrors() && success) ? "redirect:/" : null;
}

}

和失败的测试:

public void signup_duplicateEmail() throws Exception {
    AccountManager accountRepository = mock(AccountManager.class);
    AccountAuthUtils authorization = mock(AccountAuthUtils.class);
    when(accountRepository.createAccount(any(User.class))).thenThrow(new EmailAlreadyOnFileException("roy@clarkson.com"));
    SignupServiceImpl gateway = new SignupServiceImpl(accountRepository, authorization);        
    SignupController signupController = new SignupController(gateway);

    MockMvc mockMvc = standaloneSetup(signupController).build();
    mockMvc.perform(post("/register").contentType(APPLICATION_FORM_URLENCODED)
                .param("user.username","habuma")
                .param("user.email","roy%40clarkson.com")
                .param("user.password", "letmein1")
                .param("confirmPassword", "letmein1"))
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.forwardedUrl("/register.do"))
            .andExpect(MockMvcResultMatchers.model().hasErrors())
            .andExpect(MockMvcResultMatchers.model().attributeHasFieldErrors("registrationForm", "user.email"));
}

一个简单的解决方法是在控制器中返回“/register.do”而不是 null 以表示失败,但我宁愿不更改代码以使测试正常工作。

4

2 回答 2

1

我的猜测是这种差异的原因是因为在生产中您已将 ViewResolver 配置为使用“/WEB-INF/”并且可能是一个后缀。在您的独立测试设置中,您没有添加 ViewResolver,因此默认设置只是获取视图名称并将其转换为路径,此时它意识到它与请求路径相同。

至于 .do 的文档,您有意见吗?我们将很快添加一些内容,请在此处跟踪

于 2014-05-09T12:16:38.527 回答
0

好吧,经过几个小时的折腾,我明白了。

基本上,只要初始 url 与结束 url 相同,它就会给出这个问题。但是,您可以通过要求 post("register.do") (这是 servlet 所做的)来欺骗它,并检查它是否返回“register”。因此,我的解决方案是:

mockMvc.perform(post("/register.do").contentType(APPLICATION_FORM_URLENCODED)
            .param("user.username","habuma")
            .param("user.email","roy%40clarkson.com")
            .param("user.password", "letmein1")
            .param("confirmPassword", "letmein1"))
        .andExpect(MockMvcResultMatchers.status().isOk())
        .andExpect(MockMvcResultMatchers.forwardedUrl("register"))

现在它可以在测试和服务器环境中使用。

PS 我希望所有这些 .do 的东西都有很好的文档。经过多年的工作,我从未真正理解它。

于 2014-05-08T17:00:43.730 回答