Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.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
C# 如何在单元测试之间重置EF7 InMemory提供程序?_C#_Unit Testing_Entity Framework Core_Mstest - Fatal编程技术网

C# 如何在单元测试之间重置EF7 InMemory提供程序?

C# 如何在单元测试之间重置EF7 InMemory提供程序?,c#,unit-testing,entity-framework-core,mstest,C#,Unit Testing,Entity Framework Core,Mstest,我正在尝试使用EF7 InMemory提供程序进行单元测试,但是InMemory数据库在测试之间的持久性给我带来了问题 下面的代码演示了我的问题。一个测试有效,另一个测试总是失败。即使我在测试之间将\u上下文设置为null,第二次测试运行中始终会有4条记录 [TestClass] public class UnitTest1 { private SchoolContext _context; [TestInitialize] public void Setup()

我正在尝试使用EF7 InMemory提供程序进行单元测试,但是InMemory数据库在测试之间的持久性给我带来了问题

下面的代码演示了我的问题。一个测试有效,另一个测试总是失败。即使我在测试之间将
\u上下文
设置为
null
,第二次测试运行中始终会有4条记录

[TestClass]
public class UnitTest1
{
    private SchoolContext _context;

    [TestInitialize]
    public void Setup()
    {
        Random rng = new Random();
        
        var optionsBuilder = new DbContextOptionsBuilder<SchoolContext>();
        optionsBuilder.UseInMemoryDatabase();

        _context = new SchoolContext(optionsBuilder.Options);
        _context.Students.AddRange(
            new Student { Id = rng.Next(1,10000), Name = "Able" },
            new Student { Id = rng.Next(1,10000), Name = "Bob" }
        );
        _context.SaveChanges();
    }

    [TestCleanup]
    public void Cleanup()
    {
        _context = null;
    }

    [TestMethod]
    public void TestMethod1()
    {
        Assert.AreEqual(2, _context.Students.ToList().Count());
    }

    [TestMethod]
    public void TestMethod2()
    {
        Assert.AreEqual(2, _context.Students.ToList().Count());
    }
}

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class SchoolContext : DbContext
{
    public SchoolContext(DbContextOptions options) : base(options) { }

    public DbSet<Student> Students { get; set; }
}
[TestClass]
公共类UnitTest1
{
私立学校背景(u context);;
[测试初始化]
公共作废设置()
{
随机rng=新随机();
var optionsBuilder=new DbContextOptionsBuilder();
optionsBuilder.UseInMemoryDatabase();
_上下文=新的学校上下文(optionsBuilder.Options);
_context.Students.AddRange(
新学生{Id=rng.Next(110000),Name=“Able”},
新学生{Id=rng.Next(110000),Name=“Bob”}
);
_SaveChanges();
}
[测试清理]
公共空间清理()
{
_上下文=空;
}
[测试方法]
公共void TestMethod1()
{
AreEqual(2,_context.Students.ToList().Count());
}
[测试方法]
公共void TestMethod2()
{
AreEqual(2,_context.Students.ToList().Count());
}
}
公立班学生
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
公共课堂背景:DbContext
{
公立学校上下文(DbContextOptions选项):基本(选项){}
公共数据库集学生{get;set;}
}

以下调用将清除内存中的数据存储

_context.Database.EnsureDeleted();

派对有点晚了,但我也遇到了同样的问题,但我最后做的是

为每个测试指定不同的数据库名称

optionsBuilder.UseInMemoryDatabase(Guid.NewGuid().ToString());
这样你就不必再加了

_context.Database.EnsureDeleted();

在你所有的测试中,我会选择两种答案的组合。如果测试并行运行,则可以在运行另一个测试的过程中删除一个数据库,所以在运行30个测试时,我看到零星的故障。 给它一个随机的db名称,并确保它在测试完成时被删除

public class MyRepositoryTests : IDisposable {
  private SchoolContext _context;

  [TestInitialize]
  public void Setup() {
    var options = new DbContextOptionsBuilder<ApplicationDbContext>()
      // Generate a random db name
      .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
      .Options;
      _context = new ApplicationDbContext(options);
  }

  [TestCleanup]
  public void Cleanup()
    _context.Database.EnsureDeleted(); // Remove from memory
    _context.Dispose();
  }
}
公共类MyRepositoryTests:IDisposable{ 私立学校背景(u context);; [测试初始化] 公共作废设置(){ var options=new DbContextOptionsBuilder() //生成一个随机的数据库名 .UseInMemoryDatabase(数据库名称:Guid.NewGuid().ToString()) .选择; _上下文=新的ApplicationDbContext(选项); } [测试清理] 公共空间清理() _context.Database.EnsureDeleted();//从内存中删除 _context.Dispose(); } }
我使用
DbContext
夹具,如下所示

公共类DbContextFixture
其中TDbContext:DbContext
{
私有只读DbContextOptions_DbContextOptions=
新的DbContextOptionsBuilder()
.UseInMemoryDatabase(“\ux”,新的InMemoryDatabaseRoot())
.选择;
公共TDbContext CreateDbContext()
{
返回(TDbContext)(类型(TDbContext)
.GetConstructor(新[]{typeof(DbContextOptions)})
.Invoke(新[]{u dbContextOptions});
}
}
你现在可以简单地做

公共类MyRepositoryTests:IDisposable{ 私立学校背景(u context);;
有关详细信息,请参阅专用DbContextFixture。

只需更改DbContextOptions Builder的代码定义,如下所示:

        var databaseName = "DatabaseNameHere";
        var dbContextOption = new DbContextOptionsBuilder<SchoolContext>()
                                    .UseInMemoryDatabase(databaseName, new InMemoryDatabaseRoot())
                                    .Options;

此处的示例通过以下方式实现:

db..RemoveRange(db.);

下面是我的两分钱方法,以使每个单元测试彼此隔离。我使用的是C#7、XUnit和EF core 3.1

示例TestFixture类。

public class SampleIntegrationTestFixture : IDisposable
    {

        public DbContextOptionsBuilder<SampleDbContext> SetupInMemoryDatabase()
            => new DbContextOptionsBuilder<SampleDbContext>().UseInMemoryDatabase("MyInMemoryDatabase");

 private IEnumerable<Student> CreateStudentStub()
            => new List<Student>
            {
            new Student { Id = rng.Next(1,10000), Name = "Able" },
            new Student { Id = rng.Next(1,10000), Name = "Bob" }
            };

        public void Dispose()
        {
        }
   }
公共类SampleIntegrationTestFixture:IDisposable
{
公共数据库上下文选项生成器SetupInMemoryDatabase()
=>新建DbContextOptionsBuilder().UseInMemoryDatabase(“MyInMemoryDatabase”);
私有IEnumerable CreateStudentStub()
=>新列表
{
新学生{Id=rng.Next(110000),Name=“Able”},
新学生{Id=rng.Next(110000),Name=“Bob”}
};
公共空间处置()
{
}
}
样本集成测试类

 public class SampleJobIntegrationTest : IClassFixture<SampleIntegrationTestFixture >
 {
    private DbContextOptionsBuilder<SampleDbContext> DbContextBuilder { get; }
    private SampleDbContext SampleDbContext { get; set; }

 public SampleJobIntegrationTest(SampleIntegrationTestFixture 
 sampleIntegrationTestFixture )
  {
        SampleIntegrationTestFixture = sampleIntegrationTestFixture ;

        SampleDbContextBuilder = sampleIntegrationTestFixture .SetupInMemoryDatabase();
  }



  [Fact]
    public void TestMethod1()
    {
using(SampleDbContext = new SampleDbContext(SampleDbContextBuilder.Options))

        var students= SampleIntegrationTestFixture.CreateStudentStub();
            {
            SampleDbContext.Students.AddRange(students);

        SampleDbContext.SaveChanges();

  Assert.AreEqual(2, _context.Students.ToList().Count());

                SampleDbContext.Database.EnsureDeleted();
            }
      
    }
公共类SampleJobIntegrationTest:IClassFixture
{
私有DbContextOptionsBuilderDbContextBuilder{get;}
私有SampleDbContext SampleDbContext{get;set;}
公共SampleJobIntegrationTest(SampleIntegrationTestFixture
sampleIntegrationTestFixture)
{
SampleIntegrationTestFixture=SampleIntegrationTestFixture;
SampleDbContextBuilder=sampleIntegrationTestFixture.SetupInMemoryDatabase();
}
[事实]
公共void TestMethod1()
{
使用(SampleDbContext=newsampledbcontext(SampleDbContextBuilder.Options))
var students=SampleIntegrationTestFixture.CreateStudentStub();
{
SampleDbContext.Students.AddRange(Students);
SampleDbContext.SaveChanges();
AreEqual(2,_context.Students.ToList().Count());
SampleDbContext.Database.EnsureDeleted();
}
}

谢谢,它解决了我的问题。我用缩写尝试了OptionBuilder.UseInMemoryDatabase(persist:false);已从EFCore中删除,然后偶然发现了另一种可能的解决方案,用于在此处测试之间具有不同的上下文:我更喜欢所选答案的简单性,但对于测试根合成,这似乎不会重置内存数据库的标识列。因此,如果您正在为数据播种一行,则第一个选项est将看到id为1的行,第二个测试2,等等。这是设计的吗?现在是2019年,即使在数据库被删除并重新创建之后,id仍然存在的问题仍然是一个问题!很好。这修复了我的问题!我以为我的错误是我的测试是并行运行的,但实际上是in-m
public class SampleIntegrationTestFixture : IDisposable
    {

        public DbContextOptionsBuilder<SampleDbContext> SetupInMemoryDatabase()
            => new DbContextOptionsBuilder<SampleDbContext>().UseInMemoryDatabase("MyInMemoryDatabase");

 private IEnumerable<Student> CreateStudentStub()
            => new List<Student>
            {
            new Student { Id = rng.Next(1,10000), Name = "Able" },
            new Student { Id = rng.Next(1,10000), Name = "Bob" }
            };

        public void Dispose()
        {
        }
   }
 public class SampleJobIntegrationTest : IClassFixture<SampleIntegrationTestFixture >
 {
    private DbContextOptionsBuilder<SampleDbContext> DbContextBuilder { get; }
    private SampleDbContext SampleDbContext { get; set; }

 public SampleJobIntegrationTest(SampleIntegrationTestFixture 
 sampleIntegrationTestFixture )
  {
        SampleIntegrationTestFixture = sampleIntegrationTestFixture ;

        SampleDbContextBuilder = sampleIntegrationTestFixture .SetupInMemoryDatabase();
  }



  [Fact]
    public void TestMethod1()
    {
using(SampleDbContext = new SampleDbContext(SampleDbContextBuilder.Options))

        var students= SampleIntegrationTestFixture.CreateStudentStub();
            {
            SampleDbContext.Students.AddRange(students);

        SampleDbContext.SaveChanges();

  Assert.AreEqual(2, _context.Students.ToList().Count());

                SampleDbContext.Database.EnsureDeleted();
            }
      
    }