单元测试MVC控制器

14
我的ASP.NET MVC应用程序中的控制器根据一些相当简单的规则预填充由视图显示的表单数据。
似乎考虑在我的单元测试中涵盖这一点是一个好主意。但我唯一能想到验证正确数据放入表单的方式,是以一种不自然的方式从控制器中提取逻辑。
有人能建议一些方法来解决这个问题吗?
我发现的所有控制器单元测试示例都非常琐碎,比如验证它是否返回了预期类型的视图。我甚至不确定其中的价值。
2个回答

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

对我来说,检查返回的对象是否填充了正确的数据似乎并不“unnatural”,或者你的意思不同吗?


1
啊... result.Model 看起来很有用。 - Jonathan Wood

12

我认为测试返回的视图类型有点毫无意义。但是,在测试返回了预期的“视图”以及其中正确的数据的情况下,这将是一个有效的测试用例。

例如,这里是编辑控制器的单个编辑测试用例。请注意,此示例使用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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接