C# 如何在测试期间处理DatabaseFacade(单元或集成)
寻找一些建议C# 如何在测试期间处理DatabaseFacade(单元或集成),c#,asp.net-core,entity-framework-core,C#,Asp.net Core,Entity Framework Core,寻找一些建议 public class SomeController : Controller { private readonly SomeContextClass _context; public SomeController(SomeContextClass context) { _context = context; } } //Context Class public SomeContextClass : DbCont
public class SomeController : Controller
{
private readonly SomeContextClass _context;
public SomeController(SomeContextClass context)
{
_context = context;
}
}
//Context Class
public SomeContextClass : DbContext
{
public SomeContextClass(DbContextOptions<SomeContextClass> op) : base(op){
Database.SetCommandTimeout(9000);
}
}
//Test
[Fact]
public void SomeController_Test()
{
//Trying In-Memory Implementation
var options = new DbContextOptions<SomeContextClass>().UseInMemoryDatabase(databaseName: "SomeDB").Options;
using (var context = new SomeContextClass(options))
{
var sc = new SomeController(context);
}
}
public类SomeController:Controller
{
私有只读SomeContextClass_上下文;
公共SomeController(SomeContextClass上下文)
{
_上下文=上下文;
}
}
//上下文类
公共SomeContextClass:DbContext
{
公共SomeContextClass(DbContextOptions op):基本(op){
SetCommandTimeout(9000);
}
}
//试验
[事实]
公共控制器测试()
{
//尝试在内存中实现
var options=new DbContextOptions().UseInMemoryDatabase(databaseName:“SomeDB”).options;
使用(var context=newsomecontextclass(选项))
{
var sc=新的SomeController(上下文);
}
}
由于setcommandtimeoutcall,在尝试初始化somecontext类时,此错误将被忽略
有没有一种方法可以用MOQ来模拟这个呼叫?
如何在内存测试中处理它?今晚我看了一下,因为我预料它会抛出一个无效操作异常 特定于关系的方法只能在上下文使用关系数据库提供程序时使用 当您尝试使用关系方法(如FromSql、ExecuteSqlCommand等)时,这些方法在内存中提供程序中很常见。大多数情况下,它们可以使用模拟包装器进行模拟(我正是为我的库这样做的),但这通常需要大量工作 SetCommandTimeout是一个扩展。您需要深入研究扩展,并在数据库外观上模拟一些东西,以使其正常工作 然而,在我们走这条路之前,在这种情况下,嘲弄对你来说是行不通的。当您模拟一个实现时,模拟库需要能够创建一个要代理的实例,这意味着它在构造函数中执行代码。SetCommandTimeout将在模拟创建和再次barf期间传入的DbContextOptions生成的任何内容上执行 关于您的选择:
void Main()
{
using (var connection = new SqliteConnection("Filename=:memory:"))
{
connection.Open();
var options = new DbContextOptionsBuilder<TestDbContext>().UseSqlite(connection).Options;
var testDbContext = new TestDbContext(options);
Console.WriteLine(testDbContext.Database.GetCommandTimeout());
}
}
public class TestDbContext : DbContext
{
public TestDbContext(DbContextOptions<TestDbContext> op) : base(op)
{
Database.SetCommandTimeout(9000);
}
}
void Main()
{
使用(var connection=newsqliteconnection(“文件名=:内存:”)
{
connection.Open();
var options=new DbContextOptionsBuilder().UseSqlite(connection).options;
var testDbContext=newtestdbcontext(选项);
WriteLine(testDbContext.Database.GetCommandTimeout());
}
}
公共类TestDbContext:DbContext
{
公共TestDbContext(DbContextOptions op):基本(op)
{
SetCommandTimeout(9000);
}
}
结果:
您可以在DbContext配置中对超时进行硬编码,而不是硬编码。这样,上下文类保持不变 从链接文档的示例中,可以使用以下命令设置特定于提供程序的命令超时:
optionsBuilder
.UseSqlServer(connectionString,
providerOptions=>providerOptions.CommandTimeout(90));
这可以在生产或集成测试中用于设置真实数据库的命令超时,而无需修改DbContext:
var options = new DbContextOptions<SomeContextClass>()
.UseSqlServer(connectionString,
providerOptions=>providerOptions.CommandTimeout(90))
.Options;
var options=new DbContextOptions()
.UseSqlServer(连接字符串,
providerOptions=>providerOptions.CommandTimeout(90))
.选择;
超时值可以来自配置,允许在不修改代码的情况下进行更改
但是,使用内存中提供程序的单元测试不需要该设置,因此可以省略它
var options = new DbContextOptions<SomeContextClass>()
.UseInMemoryDatabase(databaseName: "SomeDB")
.Options;
var options=new DbContextOptions()
.UseInMemoryDatabase(数据库名称:“SomeDB”)
.选择;
这不是一个真正的解决方案,但我想在这里留下一个指针作为解决方法,因为它节省了我的时间。我只需要DatabaseFacade中的一件东西,我的代码就可以进行单元测试,最后我用我可以模拟的数据库上下文的虚拟方法来包装它:
public virtual bool CanConnectToDatabase()
{
return Database.CanConnect();
}
内存中提供程序有限制。。。您得到的错误是什么?这不是DatabaseFacade。DbContext作为一个工作单元,作为存储库的DbSet为什么不将超时作为DbContextOptions的一部分传递,而不是在DbContext中硬编码?OP使用的是内存上下文,它不支持通过选项设置命令超时。这就是问题所在-因为DbContext尝试设置提供程序是否支持该设置。但是,如果该设置是由调用方设置的,那么DbContext就不必猜测了。