测试控制器时如何模拟viewModel?

时间:2018-06-21 16:12:15

标签: c# asp.net unit-testing model-view-controller identityserver3

我必须如下测试我的控制器

[HttpGet]
[Route("")]
[HandleError(View= "Error")]
public ActionResult Index(string name)
{
    return View("Index", new MyViewModel){
    Name = name,
    Link = Request.UrlReferrer
   }
}

我的ViewModel如下

public class MyViewModel{
    public string Name{get;set;}
    public Uri Link{get;set}
}

我的问题是,当我编写如下的单元测试时,controller.Index(name)始终返回null,这似乎是因为我没有模拟ViewModel吗?但是,如何在函数内部模拟ViewModel呢?

我的目的是测试名称是否正确传递给ViewModel,我认为我不应该模拟MyViewModel,对吗?

此外,因为这是HttpGet,我应该模拟Http Request吗?我不确定如何在MVC.NET中测试Http请求

[TestMethod]
public void Index_Return_ViewModel(){
    string name = "name";
    var controller = new MyController(foo, bar);

    var result = controller.Index(name) as ViewResult;
    var viewModel = controller.ViewData.Model as MyViewModel;

    Assert.AreEqual("Index", result.ViewName);
}

1 个答案:

答案 0 :(得分:1)

使用以下示例控制器

public class MyController : Controller {

    [HandleError(View = "Error")]
    public ActionResult Index(string name) {
        return View("Index", new MyViewModel() {
            Name = name,
            Link = Request.UrlReferrer
        });
    }
}

为了解释答案。

由于操作访问Request.UrlReferrer,因此单元测试需要提供必要的依赖关系,以使测试得以完成。

例如

[TestMethod]
public void Index_Return_ViewModel() {
    //Arrange
    var link = new Uri("http://example.com");
    var mockContext = new Mock<ControllerContext>();
    mockContext.Setup(_ => _.HttpContext.Request.UrlReferrer)
        .Returns(link);
    string name = "name";
    var controller = new MyController() {
        ControllerContext = mockContext.Object
    };

    //Act
    var result = controller.Index(name) as ViewResult;

    //Assert
    Assert.AreEqual("Index", result.ViewName);
    var viewModel = controller.ViewData.Model as MyViewModel;
    Assert.IsNotNull(viewModel);
    Assert.AreEqual(name, viewModel.Name);
    Assert.AreEqual(link, viewModel.Link);
}

无需模拟视图模型。通过将返回的模型属性与期望值进行比较,可以确认该动作的行为符合预期。