在我的ASP.Net CORE 2.2 / EF Core 2.2 Web API应用程序中,我的DbContext中有一个HasData()方法,以使用一些标准数据为数据库播种。但是,我不想在运行xUnit测试时使用该数据。
我的单元测试使用Sqlite内存提供程序,并且作为该过程的一部分,它需要调用GuaranteeCreated()。好吧,EnsureCreated()调用了OnModelCreating(),后者调用了HasData(),所以我的单元测试上下文现在包含我不需要的所有HasData种子数据。我想用不同的,非常具体的数据作为单元测试的种子。
因为确保环境创建了种子,然后尝试添加特定于单元测试的种子数据,所以最终在测试DbContext中使用了这两组数据,并且测试失败。
如何为单元测试绕过HasData调用?
答案 0 :(得分:0)
您始终可以使用Mock
模拟调用,这将提供一种模拟使其成为接口的方法,因此上述模拟接口的函数调用实际上将在调用您的模拟函数。这将为您提供一种方法来覆盖对HasData
的函数调用。
当然,这意味着如果尚未为该功能使用接口,则必须将其包装为一个。
以下是一些有用的模拟示例:writing unit tests with NUnit and Moq和an introduction to unit testing with mocks(using moq)。
我还怀疑Theory属性和内联数据可能对您有用。 Creating parameterized tests in xUnit
希望有帮助。
答案 1 :(得分:0)
代替尝试绕过HasData(),您可以有条件地不向该方法提供数据。
快速示例-如果您将预弹出数据移至例如“ DataInitialiser”类:
builder.HasData(new UserDataInitialiser().Data);
然后在基类中设置一个静态标志:
public abstract class DataInitialiserControl
{
public static bool SkipInitData { get; set; } // ** flag **
}
public abstract class DataInitialiser<T> : DataInitialiserControl
{
public IList<T> Data => SkipInitData ? new List<T>() : GetData();
protected abstract IList<T> GetData();
}
您的DataInitialisers看起来像这样:
public class UserDataInitialiser : DataInitialiser<User>
{
protected override IList<User> GetData()
{
return new[]
{
new User {Id = 1, Name = "Bob"}
};
}
}
然后您可以在测试初始化中设置静态标志:
public abstract class TestBase
{
protected DbContextOptions<MyContext> DbOptions { get; private set; }
[TestInitialize]
public void InitializeDatabase()
{
// ** SKIP DATA PRE-POP **
DataInitialiserControl.SkipInitData = true;
DbOptions = BuildDbContextOptions(new DbContextOptionsBuilder<MyContext>()).Options;
using (var context = GetContext())
{
context.Database.EnsureCreated();
}
}
[TestCleanup]
public void ClearDatabase()
{
using (var context = GetContext())
{
context.Database.EnsureDeleted();
}
}
}
(代码未经测试,但应大致正确)。