【问题标题】:Unit Testing with Nunit, Ninject, MVC2 and the ADO.Net Entity Data Model使用 Nunit、Ninject、MVC2 和 ADO.Net 实体数据模型进行单元测试
【发布时间】:2010-07-15 15:33:12
【问题描述】:

我正在尝试使用 Nunit、Ninject、MVC2 和 ADO.Net 实体数据模型。

假设我有一个 ProductsController 实例化一个 SqlProductsRepository 类。

public class ProductsRepository : IProductsRepository
{
    public MyDbEntities _context;

    public ProductsRepository()
    {
        _context = new MyDbEntities();
    }

    public IList<Product> GetAllProducts()
    {
        return (from p in _context.Products select p).ToList();
    }
}

public class ProductsController : Controller
{
    public ActionResult ProductsList()
    {
        ProductsRepository r = new ProductsRepository();
        var products = r.GetAllProducts();

        return View(products);
    }
}

我希望能够对 ProductsRepository 执行单元测试以确保返回正确的数据,但我不确定如何编写测试类。

到目前为止,我阅读的每个教程/文档都指向我使用 IProductsRepository 创建一个 Mock 对象,然后注入和测试控制器。

在我看来,这似乎绕过了具体的实现。

MyDbEntities 来自 ADO.Net 实体数据模型 .edmx

【问题讨论】:

    标签: asp.net-mvc-2 nunit ninject ado.net-entity-data-model


    【解决方案1】:

    您完全正确- 模拟存储库确实绕过了具体实现。这才是重点。

    单元测试与功能测试不同。您的模拟对象可以设置为返回您明确定义的任何内容,然后进行测试以确保来自模拟的常量输入导致预期结果。

    【讨论】:

    • 好的,我和你在一起。我的意图是注入数据库的表示来替换上下文,以便测试存储库方法本身。这不是一件好事吗?
    • 你可以这样做,但这确实是 mocking 的目的。这个想法是您希望覆盖业务逻辑代码的每个主要路径,因此在每个测试中连接一个模拟以返回测试这些路径的结果。这将使您的测试小而紧凑。
    • 干杯。我想我在使用的术语上有混淆。我将如何创建 Mock 以测试存储库?
    • 取决于您使用的模拟工具。它们之间的语法相似。您对模拟所做的是创建一个“假”对象,您可以在其中“锁定”模拟上的方法以每次返回相同的结果。看看 NMock 和 Moq,这些是我以前见过和使用过的基于 .NET 的模拟工具。
    【解决方案2】:

    听起来您想为 ProductsRepository 创建集成测试而不是单元测试,因为您将针对数据库进行测试,以便检查它是否为您提供了正确的数据。

    在对控制器进行单元测试时,您希望模拟 ProductsRepository。

    在我对 ProductsRepository 的集成测试中,我会做一些显而易见的事情,比如

    public void TestProductsRepository()
    {
      var context = new MyDbEntities();
    
      // add a new product
    
      var products = context.GetAllProducts();
    
      // check products contains new product
    }
    

    【讨论】:

    • 我想在存储库中测试更复杂的方法,例如: GetProductByBrandNameAndProductTypeAndProductName(string brandName, string productTypeSysName, string productName) 以确保返回正确的数据。我认为这可能是一个有效的单元测试
    • 这绝对是一个有效的测试,但我可能不会将其描述为单元测试,因为您的存储库必须与实体框架集成才能获得结果。
    【解决方案3】:

    对于您的两个类(ProductsRepository、ProductsController),您应该有两组测试。每个班级一组测试。

    当(单元)测试 ProductsController 时,您应该模拟它的依赖项(在本例中为 IProductsRepository)。绕过依赖项的具体实现才是重点。

    将有一组完全不同的(集成)测试来验证 ProductsRepository 是否可以访问数据库并返回正确的数据。在这些集成测试中,您不会模拟任何内容,因为您要测试的是 real 存储库与 actual 数据库之间的交互。

    【讨论】:

      猜你喜欢
      • 2011-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多