在.NET中执行测试之前清理数据库

时间:2013-10-06 20:26:55

标签: .net database automated-tests integration-testing

方案

我们正在开发一组利用应用程序数据库的集成测试。为此,我们已将数据库切换到仅在集成测试期间使用的单独测试数据库。

通过还原SQL Server数据库快照,每次测试后,测试数据库都会重置为原始状态。这项工作没问题,但这让我们放弃了设置的头痛。

问题

是否有任何工具可以在自动化测试之前或之后更轻松地清理数据库?

我们正在使用MSTest作为我们的测试框架,但我愿意接受任何需要不同测试框架才能使数据库清理工具工作的建议。

3 个答案:

答案 0 :(得分:1)

我在使用NUnit时遇到了同样的问题,所以我创建了一个实现ITestAction(Nunit,在其他测试框架中有相同结果的东西)方法的属性,包括BeforeTest和AfterTest,并且我使用了System.Transactions程序集来存储整个断言此属性对事务进行处理后,数据库在事务中的更改(回滚)将重置事务和状态。 这里是link to my article

这是属性类:

public class ResetDatabse : Attribute, ITestAction
{

    private TransactionScope _transactionScope;
    public void BeforeTest(ITest test)
    {
        _transactionScope = new TransactionScope();
    }

    public void AfterTest(ITest test)
    {
        _transactionScope.Dispose();
    }

    public ActionTargets Targets => ActionTargets.Test;
}

答案 1 :(得分:1)

也可以使用重生。

来自 GitHub 存储库中 README.md 文件的描述。 (https://github.com/jbogard/Respawn)

"Respawn 是一个小实用程序,可帮助将测试数据库重置为干净状态。Respawn 不会在测试结束时删除数据或回滚事务,而是通过智能地从其中删除数据,将数据库重置回干净的检查点表。”

xUnit、SQL Server 和 Dapper 的示例。

using System.Data.Common;
using System.Threading.Tasks;
using Dapper;
using Microsoft.Data.SqlClient;
using Respawn;
using Xunit;

namespace TestRespawn
{
    public class ResetSqlServerFixture : IAsyncLifetime
    {
        private readonly Checkpoint _checkpoint;
        private readonly string _connectionString;

        public ResetSqlServerFixture(string connectionString)
        {
            _connectionString = connectionString;

            Connection = new SqlConnection(connectionString);

            _checkpoint = new Checkpoint();
        }

        public DbConnection Connection { get; }

        public virtual Task DisposeAsync() => _checkpoint.Reset(_connectionString);

        public virtual Task InitializeAsync() => Task.CompletedTask;
    }

    // Usage
    public class ExampleTests : ResetSqlServerFixture
    {
        public ExampleTests()
            : base(@"Server=(localdb)\MSSQLLocalDB;Integrated Security=true;")
        {
        }

        [Fact]
        public async Task GetVersion()
        {
            // Arrange
            var sqlQuery = "SELECT @@Version";

            // Action
            var version = await this.Connection.ExecuteScalarAsync(sqlQuery) as string;

            // Assert
            Assert.Contains("Microsoft", version);
        }
    }
}

答案 2 :(得分:0)

经过仔细考虑,我们找到了一个对我们有用的解决方案。

因此,在我们的单元测试开始时,我们创建了数据库的快照。我们使用SQL Server中的快照功能。

然后我们针对此快照执行测试。

测试完成后,我们再次删除快照。 这使我们的测试数据库保持清洁。

注意如果您必须在单元测试中使用数据库,我只会推荐这种工作方式。一般来说,你不应该这样做。我认为在大多数情况下,您应该能够以执行单元测试时不需要将数据存储在数据库中的方式重构代码。