Can you explain what Moq is doing here in very simple terms?
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(开发者_如何学Goprods.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.
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. The Setup
is configuring the Products
property to always return the supplied list of products (as an IQueryable) when it is called. It's then returning the generated object as a IProductsRepository
which can then be passed to ProductsController
which is none the wiser about its dynamic nature.
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.
Behind the scenes, Moq is dynamically creating an implementation of your interface IProductRepository
and making the method Products
return the IQueryable<Product>
you gave it in the Returns
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 to Returns
.
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.
精彩评论