问题描述
我的所有单元测试都有这个基类,它可以旋转内存数据库
public abstract class TestWithsqlite : Idisposable
{
private const string InMemoryConnectionString = "DataSource=:memory:";
private readonly sqliteConnection _connection;
protected readonly TodoDbContext DbContext;
protected TestWithsqlite()
{
_connection = new sqliteConnection(InMemoryConnectionString);
_connection.open();
var options = new DbContextOptionsBuilder<TodoDbContext>()
.Usesqlite(_connection)
.Options;
DbContext = new TodoDbContext(options);
DbContext.Database.EnsureCreated();
}
public void dispose()
{
_connection.Close();
}
}
我的问题是:如果我在一个测试中调用DbContext.something
,是否是dispose
方法确保在测试结束时关闭该数据库实例?这样,对于下一次测试,当我再次调用DbContext时,它是一个新实例吗?
解决方法
由于您的测试类用于多个测试,所以对于一个测试应该具有唯一性的东西使用基类是一个坏主意。
您想精确地控制 何时以及如何打开数据库以及何时以及如何将其从内存中删除。
这意味着您的类不应被继承,而应由每个测试使用。
使您的类成为可以实例化的普通类,并将通过方法或属性提供DBContext。在构造器中打开并创建数据库,然后像以前一样在dispose方法中关闭并删除数据库。
您的测试应从实例化此类的using
块开始。
在using块中,您的测试可以使用该类及其提供的DBContext。无论您如何离开测试,using块都将负责处理(代码可能最终会引发异常)。
我不记得它是如何工作的,但是我认为您可以为内存数据库命名。这样做可能是个好主意,否则您将必须确保测试永远不会并行运行。
, xUnit documentation对此进行了描述。因此包含测试的类可以实现IDisposable
。默认情况下,xUnit将隔离运行测试类中的每个方法,并将调用Dispose
,因此每个测试中的任何对象实例都是唯一的。
如果您要共享对象实例,则可以使用固定装置,但这听起来像您希望在测试之间进行隔离,默认情况下是存在的。
因此,如果您现在直接将测试方法添加到问题中的类,则每个测试的上下文应该是唯一的。您应该能够通过在测试方法(或Dispose
)中放置断点,然后调试测试以查看会发生什么来进行测试。
每个单元测试都应有一个新的DbContext。您不希望测试之间有任何依赖关系。因此,在测试结束时调用dispose是正确的。
,当我查看“ SQLite.Net帮助”时,文档指出: 处置-处置并最终确定连接。
换句话说,所有SQLiteConnection成员都变得无效,所有资源都被释放。 问候 马丁