我有两种测试方法,如下所示,测试相同的操作方法。第一个是失败,第二个是失败。这是一个Asp.net mvc4应用程序......请帮我解决这个问题......
//Action method
public ViewResult Edit(int productID)
{
Product product =
productRepository.Products.FirstOrDefault(p => p.ProductID == productID);
return View(product);
}
[TestMethod]
public void Can_Edit_Product() //Failed, result2 is set with product - "P1"
{
//Arrange
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(p => p.Products).Returns(new Product[] {
new Product{ ProductID=1, Name="P1" },
new Product{ ProductID=2, Name="P2"}
}.AsQueryable());
AdminController target = new AdminController(mock.Object);
//Act
Product result1 = target.Edit(1).ViewData.Model as Product;
Product result2 = target.Edit(3).ViewData.Model as Product;
//Assert
Assert.AreEqual("P1", result1.Name);
Assert.IsNull(result2);
}
[TestMethod]
public void Cannot_Edit_Nonexistant_Product() //Passed
{
//Arrange
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(p => p.Products).Returns(new Product[] {
new Product{ ProductID=1, Name="P1" },
new Product{ ProductID=2, Name="P2"}
}.AsQueryable());
AdminController target = new AdminController(mock.Object);
//Act
Product result2 = target.Edit(3).ViewData.Model as Product;
//Assert
Assert.IsNull(result2);
}
对于失败的测试,我发现action方法正确返回null,但不知何故Model对象未设置为null,但它被设置为第一个产品。这真的很神秘......这里发生了什么......
[在上面的代码中,productRepository.Products的类型为IQueryable ......我正在使用Moq进行模拟]
答案 0 :(得分:0)
我将第一次测试分开,但看起来你已经知道了,而你只是在寻求解释。根据您的描述,控制器ViewData.Model
第一次正确设置。所以target.ViewData.Model
是正确的。当你第二次设置它时,或许ViewData.Model
根本不会被覆盖(如果你向视图提供null
,框架可能会假设它可以忘记它,因为它是null默认)。请记住,在Web应用程序的上下文中,这些操作将被调用一次,然后所有视图数据将被丢弃,直到下一个请求。因此,下一个请求ViewData.Model
将再次以null开头。所以每个测试方法只需要一个控制器动作测试。
我没有用源代码检查过这个,但这对我来说似乎是一个可能的解释。您可以通过执行以下操作来查看我正在解释的内容。
AdminController target = new AdminController(mock.Object);
Product result1 = target.Edit(1).ViewData.Model as Product; // ViewData.Model will be product 1
Product result2 = target.Edit(3).ViewData.Model as Product; // ViewData.Model is still product 1
Product result2 = target.Edit(2).ViewData.Model as Product; // ViewData.Model will be product 2