这是我的IProductRepository:
public interface IProductsRepository
{
IQueryable<Product> Products { get; }
}
这就是我使用Moq的地方:
public static IProductsRepository MockProductsRepository(params Product[] prods)
{
var mockProductRepos = new Mock<IProductsRepository>();
mockProductRepos.Setup(x => x.Products).Returns(prods.AsQueryable());
return mockProductRepos.Object;
}
以下是我使用这个MockProductsRepository方法的方法:
[Test]
public void Product_Lists_Include_Correct_Page_Numbers()
{
//Arrange: If there are five products in the repository...
var mockRepository = UnitTestHelpers.MockProductsRepository(
new Product { Name = "P1" }, new Product { Name = "P2" },
new Product { Name = "P3" }, new Product { Name = "P4" },
new Product { Name = "P5" }
);
var controller = new ProductsController(mockRepository) { PageSize = 3 };
//yada yada yada...
}
Moq到底在做什么?我正在关注Pro ASP.Net MVC2这本书,它正在向我传授各种各样的新魔法,在我继续阅读之前,我想了解发生了什么 - 现在我只知道,“它的作品”没什么用更多。 :)
感谢您的时间。
答案 0 :(得分:4)
Moq在内存中为实现IProductsRepository
的类生成IL,其所有属性/方法都回调到Moq以查看它应该做什么。 Setup
正在配置Products
属性,以便在调用时始终返回提供的产品列表(作为IQueryable)。然后它将生成的对象作为IProductsRepository
返回,然后可以将其传递给ProductsController
,这对于它的动态性质并不明智。
答案 1 :(得分:1)
Reflection.Emit
),这是他们通常称为代理的接口的实现(虽然这个词在意义上有很多令人困惑的变化)。
对于模拟的情况,这将拦截对该接口的调用,并且具有实现以检查您对它们设置的期望。
答案 2 :(得分:0)
在幕后,Moq正在动态创建您的界面IProductRepository
的实现,并使方法Products
返回您在IQueryable<Product>
方法中提供的Returns
。< / p>
我不确定完全它是如何工作的但我认为它会为你调用Setup
的函数创建一个委托,返回给Returns
的值。
因此,您的测试代码会返回一个实现IProductRepository
接口的类,但它是一个动态创建的类,它已经重新路由某些行为以执行您指定的特定事务。然后Moq可以检查指定的事情是否已完成,验证您的期望,或者只是在您只想提供模拟数据时返回数据。