Mvc.net使用可以为null的参数进行单元测试

时间:2014-11-10 21:49:49

标签: asp.net-mvc unit-testing moq

我是Moq和Nunit的新单位测试新手。我有一个简单的单元测试来获取产品列表。但测试结果没有达到预期效果。

ProductManagementController操作是:

       public ViewResult Index(int? id)
    {
        return View(_ProductRepo.GetProductList(id));
    }

ProductRepository是:

        public IList<Product> GetProductList(int? id)
    {
        if (id == null)
        {
            return (db.Products).ToList();
        }
        else
        {
            return db.Products.Where(i => i.CategoryId == id).ToList();
        }
    }

我有两个测试设置,但只有第一个测试(获取所有产品列表)没问题。

[TestFixture]
public class Test_ProductManagement
{
    private List<Product> products;
    private List<Category> categories;
    private Mock<IProductRepository> mockProducts; 
    private ProductManagementController target;

    [TestFixtureSetUp]
    public void Initialize()
    {
        images = new List<Product> {
           new Product{Id = 1, Name = "Boat", CategoryId = 1  },
           new Product{Id = 2, Name = "Picture Frame",CategoryId = 2 }
           };

        categories = new List<Category> {
            new Category { Id = 1, Name = "Outdoors" },
            new Category { Id = 2, Name = "Housewares" }
            };

        mockProducts = new Mock<IProductRepository>();
        mockProducts.Setup(m => m.GetProductList(It.IsAny<int>())).Returns(products);
        target = new ProductManagementController(mockProducts.Object);
    } 

    [Test]
    public void Index_Contains_All_Products()
    {
        //Action
        List<Product> result = ((IEnumerable<Product>)target.Index(It.IsAny<int>()).ViewData.Model).ToList();

        //Assert
        Assert.AreEqual(2, result.Length);
        Assert.AreEqual("Boat", result[0].Name);
        Assert.AreEqual("Picture Frame", result[1].Name);
    }

    [Test]
    public void Index_Get_ImageList_By_CategoryId()
    {   //Arrange
        int id = 2;

        //Action
        List<Product> result = ((IEnumerable<Product>)target.Index(id).ViewData.Model).ToList();

        //Assert
        Assert.AreEqual(1, result.Count());
        Assert.AreEqual("Picture Frame", result[0].Name);
    }

第二次测试总是返回包含2个产品的完整产品列表,而我只希望从Assert.AreEqual(1,result.Count());返回1个

我无法弄清楚为什么测试代码总是将id作为上述索引调用中的空参数:target.Index(id)。但是,我的所有项目代码都在浏览器中正确运行。

有没有人有线索?感谢。

1 个答案:

答案 0 :(得分:1)

  

我无法弄清楚为什么测试代码总是将id作为上述索引调用中的null参数:target.Index(id)

没有。您没有显示所有代码(特别是您的控制器如何处理存储库注入),并且您似乎至少重命名了products / images字段,但代码工作正常。

您拨打target.Index(id),然后拨打_ProductRepo.GetProductList(id)。我假设这是你的模拟被调用,你Setup() 总是返回整个产品列表

模拟完全符合您的要求,此代码中未使用ProductRepository,因此您的if (id == null)永远不会被执行。

为了解决这个问题,您必须在每个测试方法中以不同方式Setup()模拟,或提前设置两种情况:

mockProducts.Setup(m => m.GetProductList(null)).Returns(products);
mockProducts.Setup(m => m.GetProductList(2)).Returns(new List<Product>{products[1]});

当然,您希望设置后一个调用稍微不那么具体,但我希望您能看到可以解决此问题的地方。