单元测试MVC控制器

Jon*_*ood 14 asp.net-mvc unit-testing asp.net-mvc-3

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

在我的单元测试中,这似乎是一件好事.但是,我可以看到验证正确数据的唯一方法是放置在表单中,这将是从控制器中提取逻辑,感觉就像一种不自然的方式.

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

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

Ron*_*ijm 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
Run Code Online (Sandbox Code Playgroud)

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


Jes*_*sse 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);
}
Run Code Online (Sandbox Code Playgroud)

控制器:

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

    return View("Edit", contact);
}
Run Code Online (Sandbox Code Playgroud)