Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sqlite 在单元测试期间,避免在EF Core 2.2中使用HasData Seed DbContext_Sqlite_Unit Testing_Asp.net Core_Entity Framework Core_Xunit - Fatal编程技术网

Sqlite 在单元测试期间,避免在EF Core 2.2中使用HasData Seed DbContext

Sqlite 在单元测试期间,避免在EF Core 2.2中使用HasData Seed DbContext,sqlite,unit-testing,asp.net-core,entity-framework-core,xunit,Sqlite,Unit Testing,Asp.net Core,Entity Framework Core,Xunit,在我的ASP.Net CORE 2.2/EF CORE 2.2 web API应用程序中,我在DbContext中有一个HasData()方法,用我使用的一些标准数据为数据库种子。但是,我不想在运行xUnit测试时使用这些数据 我的单元测试使用Sqlite内存中提供程序,作为该过程的一部分,它需要调用EnsureCreated()。好的,在调用HasData()的ModelCreating()上重新创建()调用,所以我的单元测试上下文现在包含我不想要的所有HasData种子数据。我想用不同的、非

在我的ASP.Net CORE 2.2/EF CORE 2.2 web API应用程序中,我在DbContext中有一个HasData()方法,用我使用的一些标准数据为数据库种子。但是,我不想在运行xUnit测试时使用这些数据

我的单元测试使用Sqlite内存中提供程序,作为该过程的一部分,它需要调用EnsureCreated()。好的,在调用HasData()的ModelCreating()上重新创建()调用,所以我的单元测试上下文现在包含我不想要的所有HasData种子数据。我想用不同的、非常具体的数据来进行单元测试

由于EnsureCreated()为上下文种子,然后我尝试添加特定于单元测试的种子数据,因此最终在test DbContext中出现两组数据,测试失败


如何在单元测试中绕过HasData调用?

您可以始终使用
mock
模拟调用,它将提供一种模拟接口的方法,从而使所述模拟接口的函数调用实际调用您的模拟函数。这将为您提供一种覆盖对
HasData
的函数调用的方法

当然,这意味着如果它尚未使用该函数的接口,则必须将其封装在一个接口中

下面是一些有用的例子:和

我还怀疑理论属性和内联数据可能对您有用。


希望这会有所帮助。

您可以有条件地不向该方法提供数据,而不是试图绕过HasData()

快速示例-如果将预弹出数据移出,例如“DataInitialiser”类:

然后在基类中设置静态标志:

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();
}
公共抽象类DataInitializerControl
{
公共静态bool SkipInitData{get;set;}/**标志**
}
公共抽象类DataInitializer:DataInitializerControl
{
公共IList数据=>SkipInitData?新列表():GetData();
受保护的抽象IList GetData();
}
您的数据初始化器如下所示:

public class UserDataInitialiser : DataInitialiser<User>
{
    protected override IList<User> GetData()
    {
        return new[]
        {
            new User {Id = 1, Name = "Bob"}
        };
    }
}
public类UserDataInitialiser:DataInitialiser
{
受保护的覆盖IList GetData()
{
返回新的[]
{
新用户{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();
        }
    }
}
公共抽象类TestBase
{
受保护的DbContextOptions DbOptions{get;private set;}
[测试初始化]
public void InitializeDatabase()
{
//**跳过数据预处理**
DataInitializerControl.SkipInitData=true;
DbOptions=BuildDbContextOptions(新的DbContextOptionsBuilder()).Options;
使用(var context=GetContext())
{
context.Database.recreated();
}
}
[测试清理]
公共数据库()
{
使用(var context=GetContext())
{
context.Database.EnsureDeleted();
}
}
}

(代码未经测试,但应该或多或少正确)。

我也遇到了这个问题,但找不到解决方法。我刚开始在一些测试中使用InMemory数据库提供程序。@我从常规InMemory提供程序开始,但遇到了一个问题,因为它不会重置并行运行的测试之间的标识增量,所以我得到了不可预测的主键ID。啊,这个lol也有问题。你可以通过测试插入实体的PK而不是常量来解决问题。e、 g.
var foo=ctx.Add(new foo())。。。断言相等(foo.Id,实现)应该是EF Core V3上的一个非问题。但是,如果您获得原始问题的解决方案,请告诉我。我们可以在回购协议上打开一个问题,否则:)原始问题的另一个解决方法是明确删除种子,例如
ctx.RemoveRange(ctx.Foo)
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();
        }
    }
}