Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.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# 如何使用InMemory数据库检查在单元测试中正确添加的记录_C#_Unit Testing_Entity Framework Core - Fatal编程技术网

C# 如何使用InMemory数据库检查在单元测试中正确添加的记录

C# 如何使用InMemory数据库检查在单元测试中正确添加的记录,c#,unit-testing,entity-framework-core,C#,Unit Testing,Entity Framework Core,使用InMemory数据库,我试图编写一个单元测试,它将检查一个方法是否正在向表中添加记录。该记录被添加到被测试的类中,但当我尝试重新创建时,得到了上下文处理错误。设置此测试的正确方法是什么,以便在处理上下文后检查内存中的表 单元测试 [Fact] public void Test_AddContact_AddsSuccessfully() { var contextFactoryMock = new Mock<IContextFactory>(); contextF

使用
InMemory
数据库,我试图编写一个单元测试,它将检查一个方法是否正在向表中添加记录。该记录被添加到被测试的类中,但当我尝试重新创建时,得到了上下文处理错误。设置此测试的正确方法是什么,以便在处理上下文后检查内存中的表

单元测试

[Fact]
public void Test_AddContact_AddsSuccessfully()
{
    var contextFactoryMock = new Mock<IContextFactory>();
    contextFactoryMock.Setup(x => x.CreateContext()).Returns(CreateInMemoryContactContext());

    var classUnderTest = new AddContact(contextFactoryMock.Object); 

    var response = classUnderTest.Run(new UkContactUsDto());

    using (var ctx = contextFactoryMock.Object.CreateContext()) 
    {
        var items = ctx.ContactUs.ToList(); //<--- Exception happens here due to ctx being disposed
    }
}
错误消息

无法访问已释放的上下文实例。这是一个共同的原因 错误:正在处理从中解析的上下文实例 然后尝试使用相同的上下文 实例在应用程序中的其他位置。如果您是 对上下文实例调用“Dispose”,或使用 陈述如果您使用的是依赖项注入,那么应该让 依赖注入容器负责处理上下文 实例


在Mock中,使用
DbContext
的实例模拟方法
CreateContext
。对于所有对
CreateContext
的调用,模拟将返回相同的实例。您可以通过此测试进行检查:

var context = CreateInMemoryContactContext();
var contextFactoryMock = new Mock<IContextFactory>();
contextFactoryMock.Setup(x => x.CreateContext()).Returns(context);
Assert.ReferenceEquals(context, contextFactoryMock.Object.CreateContext());
为了在上下文之间保存数据,在创建新的DbContext时需要重用相同的DbOption。对于xunit,每个测试都会实例化一个测试类的实例。您可以将初始化部分放入构造函数中:

公共类AddContactTest
{
私有DbOptions _DbOptions;
公共AddContactTest()
{
_options=new DbContextOptionsBuilder()。使用内存数据库((Guid.NewGuid().ToString())。选项
}
私有ContactContext CreateInMemoryContactContext()
{
var _inMemoryContext=新的ContactContext(_dbOptions);
在MemoryContext中返回_;
}
[事实]
公共无效测试\u添加联系人\u添加成功()
{
var contextFactoryMock=new Mock();
contextFactoryMock.Setup(x=>x.CreateContext())。返回(createInMemoryContext);
var classUnderTest=newaddcontact(contextFactoryMock.Object);
var response=classUnderTest.Run(新的UkContactUsDto());
使用(var ctx=contextFactoryMock.Object.CreateContext())
{
var items=ctx.ContactUs.ToList();
}
}
}

您正在测试的方法中处理上下文,因此无法再次使用它。一种方法是创建一个新的上下文,但您需要手动跟踪一个实例。例如:

private static readonly _memoryDatabaseRoot InMemoryDatabaseRoot = new InMemoryDatabaseRoot();

private ContactContext CreateInMemoryContactContext()
{
    var _inMemoryContext = new ContactContext(new DbContextOptionsBuilder<ContactContext>()
        .UseInMemoryDatabase("my-database", _memoryDatabaseRoot).Options);
    
    return _inMemoryContext;
}
private static readonly _memorydatabaserootinmemorydatabaseroot=new InMemoryDatabaseRoot();
私有ContactContext CreateInMemoryContactContext()
{
var_inMemoryContext=新的ContactContext(新的DbContextOptionsBuilder()
.UseInMemoryDatabase(“我的数据库”、\u memoryDatabaseRoot).Options);
在MemoryContext中返回_;
}
现在,在测试中,您可以调用
CreateInMemoryContactContext
来获取使用相同内存中数据库实例的新上下文


注意:如果要在多个测试中使用root,您可能不希望它是静态的。

我认为您的单元测试被测试的类将在这里使用不同的contexte。您的工厂将创建两个不同的上下文。我会首先尝试生成一个上下文(
使用ctx=contextFactoryMock.Object.CreateContext()),然后使用以下命令模拟工厂:
contextFactoryMock.Setup(x=>x.CreateContext())。返回(ctx);`然后,要检查添加的联系人,请使用您的初始CTX进行检查,但这样做将在测试插入的记录时创建一个新的上下文,并且使用内存数据库时,数据将消失。这是正确的,正如我尝试过的,联系人表为空。我错过了这一部分。。。您可以在不丢失数据的情况下打开和关闭上下文,但需要使用相同的
DbOptions
。但是方法
CreateInMemoryContactContext
创建一个新的
DbOption
。我将编辑我的答案。这是memoryDatabaseRoot中的私有静态只读吗_memoryDatabaseRoot=new InMemoryDatabaseRoot();使用
静态
,数据将在每次测试中重复使用。如果您希望每个测试都有一个新的样本数据,您可以删除
static
@JsonStatham它不需要是
static
,您只需要确保在创建新上下文时为测试使用相同的实例。如果有助于思考的话,你可以考虑根对象作为数据库。
var context = CreateInMemoryContactContext();
var contextFactoryMock = new Mock<IContextFactory>();
contextFactoryMock.Setup(x => x.CreateContext()).Returns(context);
Assert.ReferenceEquals(context, contextFactoryMock.Object.CreateContext());
private static readonly _memoryDatabaseRoot InMemoryDatabaseRoot = new InMemoryDatabaseRoot();

private ContactContext CreateInMemoryContactContext()
{
    var _inMemoryContext = new ContactContext(new DbContextOptionsBuilder<ContactContext>()
        .UseInMemoryDatabase("my-database", _memoryDatabaseRoot).Options);
    
    return _inMemoryContext;
}