Moq插件的用法

29 篇文章 0 订阅
12 篇文章 2 订阅

在领域驱动模型中,往往使用依赖注入,大多借助于接口实现。在ASP.NET MVC3中一个典型的应用就是在领取驱动模型中通过IRepository接口,调用实际Repository代码。那么在TDD开发过程中,我们往往还没有实现Repository代码,为了测试领域驱动模型规则(rule)的正确性,比较笨拙的方法是弄一个假设的Repository实现,现在可以借助Moq插件去快速实现Repository。

具体做法如下:

1、假设要操作产品(Product),那么定义模型:

public class Product
    {
        public int ProductID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public decimal Price { get; set; }
        public string Category { get; set; }
    }

2、然后定义存储库(Repository),引入接口解耦
    public interface IProductRepository
    {
        IEnumerable<Product> GetProducts();
        void UpdateProduct(Product p);
    }

 注意:虚拟的实现(笨拙)

    public class FakeRepository : IProductRepository
    {
        Product[] prods ={
                             new Product {Name="A",Price =50m},
                             new Product {Name="B",Price=60m},
                             new Product {Name ="C",Price =70m}
                        };
       

        public IEnumerable<Product> GetProducts()
        {
            //mock.Setup(e => e.GetProducts()).Returns(prods);
            return prods;
        }
        public int UpdatedProductCount { get; set; }
        public void UpdateProduct(Product p)
        {
            foreach (Product pro in prods.Where(e => e.Name == p.Name).Select(e => e))
            {
                pro.Price = p.Price;
            }
            UpdatedProductCount++;
        }

        public decimal GetTotalValue()
        {
            return prods.Sum(e => e.Price);
        }

       
    }

3、定义Domain模型的规则和操作

   public interface IPriceReducer
    {
        void priceReduce(decimal price);
    }

    public class MyPriceReducer : IPriceReducer
    {
       
        private IProductRepository ipr;
        public MyPriceReducer(IProductRepository ipr)
        {
            this.ipr = ipr;
        }
        public void priceReduce(decimal price)
        {
            foreach (Product p in ipr.GetProducts())
            {
                p.Price = Math.Max(p.Price-price, 1);
                ipr.UpdateProduct(p);
            }
        }
    }

测试代码:

[TestMethod]
public void AllPricesAreChanged) {
// Arrange
FakeRepository repo = new FakeRepository();
decimal reductionAmount = 10;
IEnumerable<decimal> prices = repo.GetProducts().Select(e => e.Price);
decimal[] initialPrices = prices.ToArray();
MyPriceReducer target = new MyPriceReducer(repo);
// Act
target.ReducePrices(reductionAmount);
prices.Zip(initialPrices, (p1, p2) => {
if (p1 == p2) {
Assert.Fail();
}
return p1;
});
}

使用Moq进行打桩测试:

首先,添加Moq.dll(在测试项目中),

然后,由于没有FakeRepository实现,需要准备数据:

[TestInitialize()]
        public void MyTestInitialize()
        {
            prods = new[] {
                             new Product {Name="A",Price =50m},
                             new Product {Name="B",Price=60m},
                             new Product {Name ="C",Price =70m}
                        };
        }

最好在测试方法中这样写:

[TestMethod()]
        public void AllPriceAreChanged()
        {

           
            Mock<IProductRepository> mipr = new Mock<IProductRepository>();
            mipr.Setup(e => e.GetProducts()).Returns(prods);
            MyPriceReducer target = new MyPriceReducer(mipr.Object); // TODO: 初始化为适当的值
            Decimal price = 10m; // TODO: 初始化为适当的值
            //decimal initialTotal = prods.Sum(e => e.Price);
           

            target.priceReduce(price);
            foreach (Product p in prods)
            {
                mipr.Verify(m => m.UpdateProduct(p), Times.Once());
            }
        }

      

 

注意:

1、要加using Moq;

2、Mock<>模拟

3、setup(没有实现的接口方法).returns(假设方法返回的数据),实现了不用实现方法体直接指定返回数据的核心思想

4、在domain模型中引用mock.object,达到调用具体实现的目的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值