您能用非常简单的术语解释一下 Moq 在这里做什么吗?
这是我的 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 这本书,它向我传授了各种新的魔法,在我继续阅读之前,我想了解发生了什么 - 现在我只知道,“它不起作用”更多的。 :)
谢谢您的宝贵时间。
Here is my IProductRepository:
public interface IProductsRepository
{
IQueryable<Product> Products { get; }
}
And here is where I'm using Moq:
public static IProductsRepository MockProductsRepository(params Product[] prods)
{
var mockProductRepos = new Mock<IProductsRepository>();
mockProductRepos.Setup(x => x.Products).Returns(prods.AsQueryable());
return mockProductRepos.Object;
}
And here is how I use this MockProductsRepository method:
[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...
}
What exactly is Moq doing? I'm following the book Pro ASP.Net MVC2 and it's teaching all sorts of new wizardry to me, and before I continue reading, I'd like to understand what's going on - and right now I just know, "it works" nothing more. :)
Thank you for your time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在幕后,Moq 动态创建接口
IProductRepository
的实现,并使方法Products
返回您在其中提供的IQueryable
Returns
方法。我不确定它是如何工作的,但我认为它为您调用的函数创建了一个委托
Setup
,该委托返回给Returns
的值代码>.因此,您的测试代码返回一个实现 IProductRepository 接口的类,但它是一个动态创建的类,它的某些行为已重新路由以执行您指定的特定操作。然后,Moq 可以检查指定的事情是否已完成,以验证您的期望,或者如果您只对提供模拟数据感兴趣,则仅返回数据。
Behind the scenes, Moq is dynamically creating an implementation of your interface
IProductRepository
and making the methodProducts
return theIQueryable<Product>
you gave it in theReturns
method.I'm not certain of exactly how it works but I think it creates a delegate for the function you called
Setup
on which return the value given toReturns
.So your test code gets back a class which implements the
IProductRepository
interface but it is a dynamically created class which has had some behaviour rerouted to do specific things you have specified. Moq can then check that the specified things have been done, to validate your expectations, or just return the data if you are only interested in providing mock data.Moq 正在内存中为实现 IProductsRepository 的类生成 IL,其所有属性/方法都会回调 Moq 以查看它应该执行的操作。
Setup
将Products
属性配置为在调用时始终返回提供的产品列表(作为 IQueryable)。然后,它将生成的对象作为IProductsRepository
返回,然后可以将其传递给ProductsController
,而后者对其动态性质一无所知。Moq is generating the IL in memory for a class that implements
IProductsRepository
, with all its properties/methods calling back to Moq to see what it should do. TheSetup
is configuring theProducts
property to always return the supplied list of products (as an IQueryable) when it is called. It's then returning the generated object as aIProductsRepository
which can then be passed toProductsController
which is none the wiser about its dynamic nature.模拟框架(以及其他一些 DI 框架)可以在运行时发出(通常使用
Reflection.Emit
),这是它们通常称为代理的接口的实现(尽管这个术语的含义有许多令人困惑的变化)。对于模拟的情况,这将拦截对该接口的调用,并具有实现来检查您对它们设置的期望。
Mock frameworks (as well as some other DI frameworks) can emit on runtime (usually using
Reflection.Emit
), an implementation of an interface which they usually call proxy (although this term has many confusing variations in meaning).For the case of a mock, this will intercept calls to that interface and has implementation to check the expectations you set upon them.