【问题标题】:Setup Mocked ViewModel for Unit Testing为单元测试设置 Mocked ViewModel
【发布时间】:2016-03-01 15:07:32
【问题描述】:

这里是场景:

我正在为我的控制器编写一个测试,需要设置一个名为 CheckoutViewModel 的视图模型。我的控制器方法Products没有将CheckoutViewModel作为参数,所以不能这样传递。

目前,测试返回 Null Exception 失败,因为 CheckoutViewModel 未被设置和调用。

问题:如何使用数据设置我的CheckoutViewModel

错误详情:

  • System.NullReferenceException

  • 对象引用未设置为对象的实例

当前测试

[TestMethod]
public void Products_ProductControllerIsCalled_ReturnsViewWithProducts()
{
    // Arrange
    var currentSession = _autoMoqer.GetMock<ICurrentSession>().Object;
    ProductController productController = new ProductController(currentSession);

    var checkoutViewModel = new CheckoutViewModel
    {
        CheckoutId = new Guid()
    };

    // Act
    ActionResult result = productController.Products();

    // Assert
    Assert.IsInstanceOfType(result, typeof(ViewResult));
}

控制器

 [AccectReadVerbs]
 public ActionResult Products()
 {
    CheckoutViewModel checkoutViewModel = GetCheckoutViewModel();
    var checkoutId = checkoutViewModel.CheckoutId;
    var result = _productOrchestrator.Products(checkoutId, currentSession)

    return View(result);
 }

此方法失败

private CheckoutViewModel GetCheckoutViewModel()
{
    if(Session["CheckoutViewModel"] == null)
    {
        return new CheckoutViewModel();
    }
    return (CheckoutViewModel)Session["CheckoutViewModel"];
}

【问题讨论】:

  • 你能从你的控制器显示Products()的代码吗?
  • 你能调试单元测试吗,就像进入代码一样?如果是这样,您能否确定_productOrchestrator.Products(checkoutId, currentSession) 是否实际上返回了不是NULLresult?我敢打赌这就是问题所在。
  • 当然,在调用GetCheckoutViewModel() 方法时它失败了......它在if(Session["CheckoutViewModel"] == null) 行上特别失败。
  • 看起来你需要为你的单元测试模拟 Session 对象。以How do you mock the session object collection using Moq为例。

标签: c# unit-testing tdd


【解决方案1】:

如果 GetCheckoutViewModel 对服务、dbConnection 或其他复杂类有一些依赖,则需要添加一个具有接口的类,将 GetCheckOutViewModel 的方法移动到该类,并将新接口作为对控制器的依赖。然后你需要模拟新界面。

或者编辑您的视图模型,以将接口依赖于阻碍单元测试的东西,即会话。

【讨论】:

    【解决方案2】:

    我认为你可以创建一些界面:

    public interface ISessionManager { Session session {get; set;} }

    然后你的控制器构造函数:

    public ProductsController(ISessionManager sm) { _sessionManager = sm; }

    然后您可以将模拟实例传递给您的控制器。

    【讨论】:

      【解决方案3】:

      我猜测异常是由于当您运行单元测试时没有任何(网络服务器)会话可用。您想要做的是将您的测试与任何外部依赖项隔离 - 作为网络服务器托管环境的一部分的会话状态将是外部依赖项。

      要解决这个问题,您需要从测试中模拟或存根 Session 对象。有很多方法可以做到这一点,但最简单的方法是让 Session 成为 Controller 上的公共属性。然后从您的测试中将 Session 设置为您在测试中创建的实例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-08-31
        • 1970-01-01
        • 2022-01-09
        • 2014-11-25
        • 2022-01-23
        • 1970-01-01
        • 2016-03-29
        相关资源
        最近更新 更多