RhinoMocks AssertWasCalled抛出异常

时间:2015-05-26 07:12:19

标签: c#-4.0 tdd rhino-mocks-3.5

我是TDD和RhinoMocks的新手。

我正在尝试测试AssertWasCalled但遇到问题。我测试的构造函数如下:

    public AccountControllerTests()
    {
        _webAuthenticator = MockRepository.GenerateMock<IWebAuthenticator>();
    }

我的测试是这样的:

    [TestMethod]
    public void AccountControllerCallsWebAuthenticator_CreateSignInTicketForGoodLoginCredentials()
    {
        const string username = "good-username";
        const string password = "good-password";

        var model = new LoginModel { Username = username, Password = password };

        _webAuthenticator.Stub(w => w.Authenticate(username, password)).Return(true);

        var mockHttpContextBase = MockRepository.GenerateMock<HttpContextBase>();

        var accountController = new AccountController(_webAuthenticator);

        accountController.Login(model);

        _webAuthenticator.AssertWasCalled(x => x.CreateSignInTicket(mockHttpContextBase, username));
    }

我得到的错误是:

测试方法Paxium.Music.WebUI.Tests.Controllers.AccountControllerTests.AccountControllerCallsWebAuthenticator_CreateSignInTicketForGoodLoginCredentials抛出异常: Rhino.Mocks.Exceptions.ExpectationViolationException:IWebAuthenticator.CreateSignInTicket(Castle.Proxies.HttpContextBaseProxy7f274f09b6124e6da32d96dc6d3fface,&#34; good-username&#34;);预期#1,实际#0。

我现在更改了我的代码,如下所示:代码之前和之后:

在:

public class AccountController : Controller
{
    private readonly IWebAuthenticator _webAuthenticator;

    public AccountController(IWebAuthenticator webAuthenticator)
    {
        _webAuthenticator = webAuthenticator;
    }

    [HttpGet]
    public ActionResult Login()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        if (ModelState.IsValid)
        {
            if (_webAuthenticator.Authenticate(model.Username, model.Password))
            {
                _webAuthenticator.CreateSignInTicket(HttpContext, model.Username);

                return RedirectToAction("Index", "Home");
            }

            return View(model);
        }

        return View(model);
    }
}

后:

public class AccountController : Controller
{
    private readonly IWebAuthenticator _webAuthenticator;
    private readonly HttpContextBase _contextBase;

    public AccountController()
    {

    }

    public AccountController(IWebAuthenticator webAuthenticator, HttpContextBase contextBase)
    {
        _webAuthenticator = webAuthenticator;
        _contextBase = contextBase;
    }

    [HttpGet]
    public ActionResult Login()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        if (ModelState.IsValid)
        {
            if (_webAuthenticator.Authenticate(model.Username, model.Password))
            {
                _webAuthenticator.CreateSignInTicket(_contextBase, model.Username);

                return RedirectToAction("Index", "Home");
            }

            return View(model);
        }

        return View(model);
    }
}

我的测试现在通过。当我的控制器用于实际时,我如何注入contextBase?我正在使用StructureMap。

1 个答案:

答案 0 :(得分:1)

您收到的错误消息表明Assert失败,即使用这些特定参数调用webAuthenticator对象 (因此预期为#1,实际为#0异常消息)。

从您提供的有限上下文中,我怀疑您的测试中的虚假实例HttpContextBase(mockHttpContextBase)与您的生产代码中传递给webAuthenticator 的对象不同。

有两种方法可以解决这个问题:使断言不那么严格,或者确保生产代码使用假的http上下文对象。如果你不关心在这个测试中将哪个HttpContext实例传递给webAuthenticator,你可以使用参数匹配器(Rhinomocks称它们为argument constraints)。 在你的情况下,这将是这样的:

_webAuthenticator.AssertWasCalled(x => x.CreateSignInTicket(Arg<HttpContextBase>.Is.Anything, Arg<string>.Is.Equal(username)));