设想
我们正在开发一组使用应用程序数据库的集成测试。为此,我们已经将数据库切换到仅在集成测试期间使用的单独测试数据库。
每次测试后,通过还原 SQL Server 数据库快照将测试数据库重置为其原始状态。这工作正常,但它让我们不再头疼设置。
问题
是否有任何工具可以在自动化测试之前或之后更轻松地清理数据库?
我们使用 MSTest 作为我们的测试框架,但我愿意接受任何需要不同测试框架才能使数据库清理工具工作的建议。
我们正在开发一组使用应用程序数据库的集成测试。为此,我们已经将数据库切换到仅在集成测试期间使用的单独测试数据库。
每次测试后,通过还原 SQL Server 数据库快照将测试数据库重置为其原始状态。这工作正常,但它让我们不再头疼设置。
是否有任何工具可以在自动化测试之前或之后更轻松地清理数据库?
我们使用 MSTest 作为我们的测试框架,但我愿意接受任何需要不同测试框架才能使数据库清理工具工作的建议。
我在使用 NUnit 时遇到了同样的问题,所以我创建了一个实现 ITestAction 的属性(Nunit,在其他测试框架中有相同的结果)方法,包括 BeforeTest 和 AfterTest 我使用 System.Transactions 程序集将整个数据库更改存储在断言此属性后的事务处理(回滚)事务和状态将被重置。这是我关于它的文章的链接。
这是属性类:
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;
}
经过仔细考虑,我们找到了一个非常适合我们的解决方案。
因此,在我们的单元测试开始时,我们创建了数据库的快照。为此,我们使用 SQL Server 中的快照功能。
然后我们针对这个快照执行测试。
测试完成后,我们再次删除快照。这使我们的测试数据库保持干净。
请注意,如果您绝对必须在单元测试中使用数据库,我只会推荐这种工作方式。一般来说,你不应该。我认为在大多数情况下,您应该能够以一种在执行单元测试时不需要将内容存储在数据库中的方式重构您的代码。
也可以使用重生。
来自 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);
}
}
}
请查看我正在开发以解决该场景的Reseed库。
该库能够通过TRUNCATE
在有序表图上使用类似于另一个答案中提到的 Respawn 的语句来快速清理数据库。它巧妙地做到了这一点,甚至能够通过禁用约束来处理表和行级别上的依赖循环。
此外,它能够为您插入测试数据,因此它基本上提供与数据库快照相同的行为。我在快照性能方面遇到了问题,所以最终得到了一个库。
尽管它仍处于积极开发阶段,但我将它用于我的一些项目,到目前为止运行良好。