你能用非常简单的术语解释一下Moq在做什么吗?

时间:2011-03-16 13:47:32

标签: c# interface 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这本书,它正在向我传授各种各样的新魔法,在我继续阅读之前,我想了解发生了什么 - 现在我只知道,“它的作品”没什么用更多。 :)

感谢您的时间。

3 个答案:

答案 0 :(得分:4)

Moq在内存中为实现IProductsRepository的类生成IL,其所有属性/方法都回调到Moq以查看它应该做什么。 Setup正在配置Products属性,以便在调用时始终返回提供的产品列表(作为IQueryable)。然后它将生成的对象作为IProductsRepository返回,然后可以将其传递给ProductsController,这对于它的动态性质并不明智。

答案 1 :(得分:1)

模拟框架(以及其他一些DI框架)可以在运行时发出 (通常使用Reflection.Emit),这是他们通常称为代理的接口的实现(虽然这个词在意义上有很多令人困惑的变化)。

对于模拟的情况,这将拦截对该接口的调用,并且具有实现以检查您对它们设置的期望。

答案 2 :(得分:0)

在幕后,Moq正在动态创建您的界面IProductRepository的实现,并使方法Products返回您在IQueryable<Product>方法中提供的Returns。< / p>

我不确定完全它是如何工作的但我认为它会为你调用Setup的函数创建一个委托,返回给Returns的值。

因此,您的测试代码会返回一个实现IProductRepository接口的类,但它是一个动态创建的类,它已经重新路由某些行为以执行您指定的特定事务。然后Moq可以检查指定的事情是否已完成,验证您的期望,或者只是在您只想提供模拟数据时返回数据。