C# 为单元测试设置模拟ViewModel
以下是场景: 我正在为我的控制器编写测试,需要设置一个名为C# 为单元测试设置模拟ViewModel,c#,unit-testing,tdd,C#,Unit Testing,Tdd,以下是场景: 我正在为我的控制器编写测试,需要设置一个名为CheckoutViewModel的视图模型。我的控制器方法,Products没有将CheckoutViewModel作为参数,因此我无法以这种方式传递它 当前,由于未设置和调用CheckoutViewModel,测试无法返回Null异常 问题:如何使用数据设置我的CheckoutViewModel 错误详细信息: System.NullReferenceException 对象引用未设置为对象的实例 当前测试 [TestMethod
CheckoutViewModel
的视图模型。我的控制器方法,Products
没有将CheckoutViewModel
作为参数,因此我无法以这种方式传递它
当前,由于未设置和调用CheckoutViewModel
,测试无法返回Null异常
问题:如何使用数据设置我的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));
}
此方法失败
private CheckoutViewModel GetCheckoutViewModel()
{
if(Session["CheckoutViewModel"] == null)
{
return new CheckoutViewModel();
}
return (CheckoutViewModel)Session["CheckoutViewModel"];
}
如果GetCheckoutViewModel对服务、dbConnection或其他复杂类具有某些依赖关系,则需要添加一个带有接口的类,将GetCheckoutViewModel的方法移动到该类,并将新接口作为控制器的依赖关系。然后需要模拟新接口
或者编辑您的viewmodel,使接口依赖于阻碍单元测试的东西,即会话。我认为您可以创建一些接口:
公共接口ISessionManager
{
会话{get;set;}
}
然后,您的控制器构造函数:
公共产品控制器(ISessionManager sm)
{
_会话管理器=sm;
}
然后,您可以将模拟实例传递给控制器。我猜想,出现异常的原因是,当您运行单元测试时,将没有任何(Web服务器)会话可用。您要做的是将测试与任何外部依赖项隔离开来,而作为Web服务器宿主环境一部分的会话状态将是外部依赖项
要解决这个问题,您需要从测试中模拟或删除会话对象。有很多方法可以做到这一点,但最简单的方法是使会话成为控制器上的公共属性。在测试中,您可以将会话设置为在测试中创建的实例 能否从控制器中显示Products()
的代码?能否按照代码中的步骤调试单元测试?如果是这样,您能否确定\u productOrchestrator.Products(checkoutId,currentSession)
是否实际返回一个非空的结果?我打赌这就是问题所在。当然,调用GetCheckoutViewModel()
方法时失败。。。它在if(Session[“CheckoutViewModel”]==null)
行中特别失败。看起来您需要模拟Session
对象进行单元测试。举一个例子来看。
private CheckoutViewModel GetCheckoutViewModel()
{
if(Session["CheckoutViewModel"] == null)
{
return new CheckoutViewModel();
}
return (CheckoutViewModel)Session["CheckoutViewModel"];
}