在每个单元测试之前重新创建和重新设置LocalDb

Ray*_*lli 13 unit-testing entity-framework ef-code-first asp.net-web-api localdb

我正在尝试为我的ASP.NET Web API项目编写单元/集成测试,并努力孤立地运行每个测试.请允许我解释一下.

我有一个配置了部署设置的*.testsettings文件.在每次测试运行之前,将一个空的*.mdf文件部署到测试位置.由于我正在使用实体框架代码优先,我可以使用数据库初始化程序将我的模式推送到数据库并为2行播种特定的表.这非常有效.

我面临的问题是,如果他们以错误的顺序执行,我所有ApiControllers操作的各种测试都会踩到彼此的脚趾上.例如,如果我在POST测试之前运行GET测试,那么GET返回2个对象,如果它们以相反的顺序运行,则GET返回3个对象.

我认为我需要做的是在每次测试之前删除,重新创建和重新设置我的数据库.这是个好主意还是有更好的方法?如果这是我能做的最好的,我会在每次测试之前重新设置数据库.

Ray*_*lli 21

这就是我最终为感兴趣的人做的事情.

我扩展DropCreateDatabaseAlways<TContext>并覆盖了Seed方法,用我的单元测试可以依赖的已知测试数据填充我的数据库.

public class MyDatabaseInitializer : System.Data.Entity.DropCreateDatabaseAlways<MyDbContext>
{
    protected override void Seed(MyDbContext context)
    {
        // Add entities to database.

        context.SaveChanges();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我实现了一个[AssemblyInitialize]设置数据库初始化程序的方法.

[TestClass]
public class Global
{
    [AssemblyInitialize]
    public static void AssemblyInitialize(TestContext context)
    {
        System.Data.Entity.Database.SetInitializer(new MyDatabaseInitializer());
    }
}
Run Code Online (Sandbox Code Playgroud)

这将为数据库设置初始化程序,但实际上并未运行它.intitializer在[TestInitialize]我编写的方法中运行,该方法强制在每次测试之前删除,重新创建和重新植入数据库.

[TestClass]
public class MyTestClass
{
    [TestInitialize]
    public void TestInitialize()
    {
        MyDbContext context = new MyDbContext();
        context.Database.Initialize(true);
    }

    [TestMethod]
    public void MyUnitTest()
    {
        Assert.IsTrue(true);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 唯一完整的答案如何重新创建localdb :-)在我的情况下我不得不添加`AppDomain.CurrentDomain.SetData("DataDirectory",AppDomain.CurrentDomain.BaseDirectory);````TestInitialize`来动态设置数据库路径,因为我在我的连接字符串中有这个:`AttachDBFilename = | DataDirectory |\TestDb.mdf` (2认同)

Chr*_*ris 6

我建议您在开始测试之前重新创建数据库,然后将它们包装在始终回滚的事务中。如果您的重新创建阶段需要很多时间才能完成(例如,由于需要执行的操作等),这将非常有益。

  • 这里有一些示例代码将非常有益! (3认同)