正在寻找一些建议。
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);
}
}
由于setcommandtimeoutcall,尝试初始化某些上下文类时出现此错误。
有没有一种使用最小起订量来模拟该呼叫的方法? 如何在内存测试中处理它?</ p>
答案 0 :(得分:0)
我今晚看了一眼,因为我期望它会引发InvalidOperationException
仅当上下文使用关系数据库提供程序时,才可以使用特定于关系的方法。
当您尝试使用诸如FromSql,ExecuteSqlCommand等关系方法时,这些在内存提供程序中很常见。大多数情况下,可以使用模拟包装器对它们进行模拟(我对我的库EntityFrameworkCore.Testing做到了这一点),但通常需要做很多工作。
SetCommandTimeout是扩展。您需要深入研究扩展,并在数据库外观上模拟一些内容才能使其正常工作。
但是,在我们走这条路之前,在这种情况下,模拟对您不起作用。在模拟实现时,模拟库需要能够创建实例以进行代理,这意味着它将在构造函数中执行代码。 SetCommandTimeout将在模拟创建过程中生成的任何传递给您的DbContextOptions上执行,并再次执行barf。
根据您的选择:
不要在构造函数中调用set命令超时;将其移至另一种方法,记得调用它,等等
使用支持关系操作的其他实体框架核心提供程序
不能说我喜欢第一个选项,但是它将允许您模拟它。第二个更可口。我对SQLite并没有做很多事情,但是快速使用LINQPad可以产生预期的结果:
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);
}
}
结果:
答案 1 :(得分:0)
您可以set it through DbContextOptions,而不是在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<SomeContextClass>()
.UseInMemoryDatabase(databaseName: "SomeDB")
.Options;
答案 2 :(得分:0)
不是真正的解决方案,但我想在这里留下一个解决方法的指针,因为 this answer 挽救了我的一天。我只需要 DatabaseFacade 中的一件事就可以让我的代码进行单元测试,最后我用我可以模拟的数据库上下文的虚拟方法包装它:
public virtual bool CanConnectToDatabase()
{
return Database.CanConnect();
}