Asp.net 在进行TDD时,如何最好地创建测试数据库?

Asp.net 在进行TDD时,如何最好地创建测试数据库?,asp.net,tdd,dependency-injection,mocking,persistence,Asp.net,Tdd,Dependency Injection,Mocking,Persistence,在创建ASP.NET站点(例如ASP.NET MVC站点)时,创建测试持久性层的最佳实践是什么 我看到的许多例子都在单元测试项目中使用Moq(或其他模拟框架),但我想,比如。。moq去掉了我的持久层,这样我的网站就可以显示数据和东西,但它不是来自数据库。我想最后再做。我见过的所有嘲弄的东西都只存在于单元测试中 当人们想要(存根?)伪造一个持久性层以进行快速开发时,他们会做什么?我使用依赖注入来处理它,并为我的持久性层(这真的是手动的,很无聊)提供了一些硬编码的结果 其他人在干什么?示例和链接将非

在创建ASP.NET站点(例如ASP.NET MVC站点)时,创建测试持久性层的最佳实践是什么

我看到的许多例子都在单元测试项目中使用Moq(或其他模拟框架),但我想,比如。。moq去掉了我的持久层,这样我的网站就可以显示数据和东西,但它不是来自数据库。我想最后再做。我见过的所有嘲弄的东西都只存在于单元测试中

当人们想要(存根?)伪造一个持久性层以进行快速开发时,他们会做什么?我使用依赖注入来处理它,并为我的持久性层(这真的是手动的,很无聊)提供了一些硬编码的结果

其他人在干什么?示例和链接将非常棒:)

更新 只是一个小小的更新:到目前为止,我已经从一个假的存储库和一个SQL存储库中获得了相当多的收益——其中每个类都实现了一个接口。然后,使用DI(我使用的是StructureMap),我可以在假存储库和SQL存储库之间切换。到目前为止,它运行良好:)


(想想我在将近11个月前问过这个问题也很可怕,当时我正在编辑这篇文章!)

假设您使用的是Rob Connery的MVC Store Front中的存储库模式:

我遵循了Rob Conry的教程,但遇到了与你相同的需求。最好的办法是将您创建的模拟存储库移动到一个名为Mock的单独项目中,然后在实例化服务时,您可以非常轻松地将它们与真实的存储库交换。如果您觉得有冒险精神,可以创建一个工厂,从配置文件中获取一个值来实例化一个模拟或真实的存储库

e、 g

或者使用依赖项注入框架:)

container.Resolve();
祝你好运

编辑:响应您的评论,听起来您想使用列表和LINQ来模拟db的操作,例如GetProducts、StoreProduct。我以前做过这个。下面是一个例子:

public class Product
{
     public int Identity { get; set; }
     public string Name { get; set; }
     public string Description { get; set; }
     //etc
}

public class FakeCatalogRepository()
{
     private List<Product> _fakes;

     public FakeCatalogCatalogRepository()
     {
          _fakes = new List<Product>();

          //Set up some initial fake data
          for(int i=0; i < 5; i++)
          {
              Product p = new Product
              {
                 Identity = i,
                 Name = "product"+i,
                 Description = "description of product"+i
              };

              _fakes.Add(p);
          }
     }

     public void StoreProduct(Product p)
     {
         //Emulate insert/update functionality

         _fakes.Add(p);
     }

     public Product GetProductByIdentity(int id)
     {
          //emulate "SELECT * FROM products WHERE id = 1234
          var aProduct = (from p in _fakes.AsQueryable()
                         where p.Identity = id
                         select p).SingleOrDefault();

          return aProduct;
     }
}
公共类产品
{
公共整数标识{get;set;}
公共字符串名称{get;set;}
公共字符串说明{get;set;}
//等
}
公共类FakeCatalogRepository()
{
私人名单(伪造品);;
公共伪造目录存储库()
{
_伪造=新列表();
//设置一些初始假数据
对于(int i=0;i<5;i++)
{
产品p=新产品
{
身份=我,
Name=“product”+i,
Description=“产品说明”+i
};
_添加(p);
}
}
公共产品(产品p)
{
//模拟插入/更新功能
_添加(p);
}
公共产品GetProductByIdentity(int id)
{
//模拟“从id=1234的产品中选择*
var aProduct=(来自fakes.AsQueryable()中的p)
其中p.Identity=id
选择p).SingleOrDefault();
退回产品;
}
}

这更有意义吗?

不管无聊与否,我认为你的思路是正确的。我假设你正在创建一个伪造的存储库,它是你的IRepository的具体实现,然后被注入到你的服务层中。这很好,因为在将来的某个时候,当你对实体的形状和作为服务、控制器和视图的一员,您可以测试真正的存储库,这些存储库将使用数据库来持久化这些实体。当然,这些测试的性质将是集成测试,但如果不是更重要的话,也同样重要

当您需要创建真正的存储库时,有一件事可能会让您不那么无聊,那就是如果您使用nHibernate进行持久化,那么您将能够在为实体创建nHibernate映射后让nHibernate生成您的数据库,前提是您不必使用遗留模式

例如,我的SetUpFixture调用了以下方法来生成我的db模式:

public class SchemaBuilder
{
   public static void ExportSchema()
    {
        Configuration configuration = new Configuration();
        configuration.Configure();
        new SchemaExport(configuration).Create(true, true);
    }
}
我的设置如下:

[SetUpFixture]
public class SetUpFixture
{
    [SetUp]
    public void SetUp()
    {
        SchemaBuilder.ExportSchema();
        DataLoader.LoadData();
    }
}
其中DataLoader负责使用real respoitory创建所有种子数据和测试数据

这可能无法回答您的问题,但我希望它能让您在方法上放心


<格雷戈>

我在一个单元测试类中的一个安装方法中运行了创建表和数据的路径,运行测试,然后在拆卸过程中进行清理。是的,这个方法是有效的,但是如果你真的结束了你的单元测试的调试目的,你总是会运行安装程序,调试一些东西,然后停在中间而不做TH。它非常脆弱,你很可能最终(从长远来看)会测试数据库中有坏数据和/或无法使用的单元测试。我个人认为最好使用模拟框架模拟数据库层。我确实理解,有时最好在数据库中进行逻辑操作。在这些情况下,您可以使用类似于为数据库层编写测试的工具。

尽管我没有使用Asp.Net或MVC框架我确实需要在不影响数据库的情况下测试服务。你的问题引发了一篇短文的撰写(好的,也许不那么短文)总结我是如何做到这一点的。不是说它是最好的或任何东西,但它对我们有用。我们通过存储库访问数据,需要时我们插入内存存储库,如本文所述


我正在使用一个包含SQLite和ActiveRecord的完整内存数据库。基本上,我们在运行每个集成测试之前删除并重新创建数据库,以便数据始终处于已知状态。数据库的内容通过代码插入。因此示例如下:

ActiveRecord.Initalize(lots of parameters)
ActiveRecord.DropSchema();
ActiveRecord.CreateSchema();
然后我们就增加了很多客户,或者随便什么,DDD风格:

customerRepository.Save(customer);
另一种解决方法是使用NDbUnit t
ActiveRecord.Initalize(lots of parameters)
ActiveRecord.DropSchema();
ActiveRecord.CreateSchema();
customerRepository.Save(customer);