Mvc3(2)

摘录于Pro ASP.NET MVC3 Framework一书:

Unit Test里用到的Moq技术【在单元测试项目里面加入对Moq.dll的引用】

接口定义:    

public interface IProductRepository    

{        

IEnumerable<Product> GetProducts();    

}

接口的实现类:    

    public class FakeRepository : IProductRepository
    {
        //275M,数字后面加m或M,表示是decimal类型,128位
        private Product[] products = new Product[] {
                                     new Product() { Name = "Kayak", Price = 275M},
                                     new Product() { Name = "Lifejacket", Price = 48.95M},
                                     new Product() { Name = "Soccer ball", Price = 19.50M},
                                     new Product() { Name = "Stadium", Price = 79500M}
                                 };
        public IEnumerable<Product> GetProducts()
        {
            return products;
        }
        public decimal GetTotalValue()
        {
            return products.Sum(e => e.Price);
        }
    }

另一接口:
    public interface IPriceReducer
    {
        void ReducePrices(decimal priceReduction);
    }

该接口的实现类:
    public class MyPriceReducer : IPriceReducer
    {
        private IProductRepository repository;
        //依赖于IProductRepository接口
        public MyPriceReducer(IProductRepository repo)
        {
            this.repository = repo;
        }
        public void ReducePrices(decimal priceReduction)
        {
            foreach (var item in repository.GetProducts())
            {
                item.Price = Math.Max(item.Price - priceReduction, 1);
                repository.UpdateProduct(item);
            }
        }
    }

没有用Moq技术的单元测试用例:【需要项目中的FakeRepository类】
        [TestMethod]
        public void CorrectTotalReductionAmount()
        {
            //
            FakeRepository repo = new FakeRepository();
            decimal reductionAmount = 10;
            decimal initialTotal = repo.GetTotalValue();
            MyPriceReducer target = new MyPriceReducer(repo);
            target.ReducePrices(reductionAmount);     
            Assert.AreEqual(repo.GetTotalValue(),
            (initialTotal - (repo.GetProducts().Count() * reductionAmount))
            );
        }

用到Moq技术的单元测试用例:
        [TestMethod]
        public void CorrectTotalReductionAmount2()
        {
            Product[] products = new Product[] {
                                                new Product() { Name = "Kayak", Price = 275M},
                                                new Product() { Name = "Lifejacket", Price = 48.95M},
                                                new Product() { Name = "Soccer ball", Price = 19.50M},
                                                new Product() { Name = "Stadium", Price = 79500M}
                                               };
            //此时是不需要IProductRepository接口的实现类的,也就是项目中不用手写一个IProductRepository接口的实现类,Moq可以模拟一个这样的实现类,
            Mock<IProductRepository> mock = new Mock<IProductRepository>();
            //当调用IProductRepository中的GetProducts()方法时,返回products
            mock.Setup(m => m.GetProducts()).Returns(products);
            decimal reductionAmount = 10;
            decimal initialTotal = products.Sum(p => p.Price);
            //把Moq模拟的这个对象传给MyPriceReducer
            MyPriceReducer target = new MyPriceReducer(mock.Object);
            target.ReducePrices(reductionAmount);
            Assert.AreEqual(products.Sum(p => p.Price),
            (initialTotal - (products.Count() * reductionAmount)));
        }

//以上数据源products是声明在一个测试方法中的,为了代码简洁,可以把products声明在这个测试类中【这样需要用到数据源的其他测试方法都可以引用它】,如:

    [TestClass()]
    public class MyPriceReducerTest
    {
        private IEnumerable<Product> products;
        [TestInitialize]
        public void PreInitialize()
        {
            products = new Product[] {
                                        new Product() { Name = "Kayak", Price = 275M},
                                        new Product() { Name = "Lifejacket", Price = 48.95M},
                                        new Product() { Name = "Soccer ball", Price = 19.50M},
                                        new Product() { Name = "Stadium", Price = 79500M}
                                     };
        }

     }

属性[TestInitialize]:在运行每一个测试用例之前,都会先进行调用PreInitialize()方法

原文地址:https://www.cnblogs.com/notebook2011/p/2799647.html