使用Recaptcha对Action进行单元测试

时间:2011-07-12 16:56:51

标签: asp.net-mvc unit-testing asp.net-mvc-3

我如何测试控制器的以下动作:

 public ActionResult Edit(User usr)
    {
        if (!Microsoft.Web.Helpers.ReCaptcha.Validate(ConfigurationManager.AppSettings["reCaptchaPrivate"].ToString()))
        {
            ModelState.AddModelError("reCaptcha", PPRR.App_LocalResources.Global.ErrorFillReCaptcha);
            return PartialView("Wrong", usr);
        }
        if (ModelState.IsValid)
        {code..... }}

2 个答案:

答案 0 :(得分:7)

我首先要抽象出Captcha验证码:

public interface ICaptchaValidator
{
    bool Validate();
}

然后我的控制器看起来像这样:

public class FooController: Controller
{
    private readonly ICaptchaValidator _validator;
    public FooController(ICaptchaValidator validator)
    {
        _validator = validator;
    }

    public ActionResult Edit(User usr)
    {
        if (!_validator.Validate())
        {
            ModelState.AddModelError("reCaptcha", PPRR.App_LocalResources.Global.ErrorFillReCaptcha);
            return PartialView("Wrong", usr);
        }

        ...
    }
}

现在,您已经削弱了控制器与验证验证码的方式之间的耦合。这是一件好事,因为它使您的控制器操作更容易进行单元测试。我们已经成功地使我们的控制器独立于实现验证的实际方式。

现在只需选择一个模拟框架,如Rhino Mocks,Moq,NSubstitute,并在单元测试中将一个存根验证器注入此控制器,以便您可以在其上定义行为。

我个人会建议你MvcContrib.TestHelper(基于Rhino Mocks)来测试你的ASP.NET MVC应用程序。它有许多内置的好东西可以模拟HttpContext并使单元测试变得容易。

以下是如何测试验证失败案例的示例:

[TestMethod]
public void FooController_Edit_Action_Should_Return_The_Wrong_Partial_If_Captcha_Validation_Fails()
{
    // arrange
    var validatorStub = MockRepository.GenerateStub<ICaptchaValidator>();
    var sut = new HomeController(validatorStub);
    var user = new User();
    validatorStub.Stub(x => x.Validate()).Return(false);

    // act
    var actual = sut.Edit(user);

    // assert
    actual
        .AssertPartialViewRendered()
        .ForView("Wrong")
        .WithViewData<User>()
        .Equals(user);
    Assert.IsFalse(sut.ModelState.IsValid);
}

答案 1 :(得分:2)

作为Darin答案的替代方案,我之前使用过自定义ActionFilter来处理验证码,并将错误添加到ModelState。它工作得很好,意味着验证码不是动作方法本身的一部分。