单元测试MVC控制器

时间:2011-12-19 14:38:47

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

我的ASP.NET MVC应用程序中的控制器根据一些相当直接的规则预先填充我的视图显示的表单数据。

在我的单元测试中,这似乎是一件好事。但是,我能看到验证正确数据的唯一方法是放在表单中,就是从控制器中提取出一种不自然的方式。

有人可以提出解决方法吗?

我发现的单元测试控制器的所有示例似乎都非常简单,例如验证它返回了预期的视图类型。我不确定我是否看到了它的价值。

2 个答案:

答案 0 :(得分:21)

您可以通过将返回的对象强制转换为适当的类来进行测试,而不是使用它们的基类(默认情况下返回)

例如,要测试默认的AccountController,请执行以下操作:

var controller = new AccountController();
var result = controller.LogOn() as ViewResult;
var model = result.Model as LogOnModel;

Assert.IsTrue(model.RememberMe); // assuming you "pre-populated" enabled the checkbox

检查返回的对象是否填充了正确的数据似乎"不自然"对我来说,还是你的意思不同?

答案 1 :(得分:12)

我同意测试返回的视图类型有点毫无意义。但是,测试返回预期的“视图”及其正确的数据将是IMO的有效测试用例。

例如,这里是编辑控制器的单一编辑测试用例。请注意,这个例子正在使用Moq和Nunit,但除此之外它是相当直接的。

请注意,ViewResult会强制转换为预期的视图模型,然后针对预期的联系进行断言。

测试:

[Test]
public void Edit_Get_Should_Lookup_Contact_From_Repository_And_Return_Edit_View()
{
    // arrange
    var _repository = new Mock<IContactRepository>();

    var expectedContact = new Contact
    {
        First = "first",
        Last = "last",
        Email = "mail@test.com"
    };

    var mockContext = new Mock<ControllerContext>();
    _repository.Setup(x => x.GetById(It.IsAny<int>())).Returns(expectedContact);

    var controller = new ContactController(_repository.Object)
    {
        ControllerContext = mockContext.Object
    };

    // act
    var result = controller.Edit(1) as ViewResult;
    var resultData = (Contact)result.ViewData.Model;

    // assert
    Assert.AreEqual("Edit", result.ViewName);
    Assert.AreEqual(expectedContact.First, resultData.First);
    Assert.AreEqual(expectedContact.Last, resultData.Last);
    Assert.AreEqual(expectedContact.Email, resultData.Email);
}

控制器:

[HttpGet]
public ActionResult Edit(int id)
{
    var contact = _repository.GetById(id);

    return View("Edit", contact);
}
相关问题