C# 模仿企业图书馆5';数据库';

C# 模仿企业图书馆5';数据库';,c#,.net,unit-testing,enterprise-library,C#,.net,Unit Testing,Enterprise Library,是否可以模拟企业库5版本的“数据库”?如果是的话。。。怎么做? 没有IDatabase接口(这是一个谜,因为我认为微软p&p会更关注公开这样一个接口的可测试性好处) 我有一个使用EntLib 5数据访问应用程序块的存储库类 我正在将单元测试重新装配到这个类中,需要模拟对数据库对象的依赖关系。该类现在通过其构造函数传递给数据库,并使用数据库对象对数据库执行操作 我使用以下方法解析要传递到我的存储库的数据库实例: Container.RegisterType<IFooRepository, F

是否可以模拟企业库5版本的“数据库”?如果是的话。。。怎么做?

没有IDatabase接口(这是一个谜,因为我认为微软p&p会更关注公开这样一个接口的可测试性好处)

我有一个使用EntLib 5数据访问应用程序块的存储库类

我正在将单元测试重新装配到这个类中,需要模拟对数据库对象的依赖关系。该类现在通过其构造函数传递给数据库,并使用数据库对象对数据库执行操作

我使用以下方法解析要传递到我的存储库的数据库实例:

Container.RegisterType<IFooRepository, FooRepository>(
    new InjectionConstructor(
        EnterpriseLibraryContainer.Current.GetInstance<Database>("FooDbConnStr")
    )
);
Container.RegisterType(
新注入构造函数(
EnterpriseLibraryContainer.Current.GetInstance(“FooDbConnStr”)
)
);
我不希望这些单元测试成为集成测试。

我曾尝试使用Moq创建数据库类型的动态模拟,但事实证明这很棘手,因为数据库的构造函数中需要连接字符串和DbProviderFactory。也许如果有一个MockDbProviderFactory这样的东西

这是单元测试采用的形式:

旁白:我还发现静态记录器类的使用很难测试。希望我在这里错过了一些技巧,但我必须说,到目前为止,我对可测试性感到失望。

我使用了FakeiTasy

我创建了一个SqlDatabase的模拟(使用更友好的构造函数从数据库继承)将其传递给FooRepostory,调用测试中的函数,并断言对数据库进行的预期调用

[Test]
public void FooRepo_CallsCorrectSPOnDatabase()
{
    var mockDb = A.Fake<SqlDatabase>(x => x.WithArgumentsForConstructor(new object[] { "fakeconnStr" }));
    var sut = new FooRepository(mockDb);
    sut.LoadFoosById(1);
    A.CallTo(() => mockDb.GetStoredProcCommand(Db.SProcs.GetFoosById)).MustHaveHappened(Repeated.Once);
}
[测试]
public void FooRepo_CallsCorrectSPOnDatabase()
{
var mockDb=A.Fake(x=>x.WithArgumentsForConstructor(新对象[]{“fakeconnStr”}));
var sut=新FooRepository(mockDb);
sut.loadfoosbyd(1);
A.CallTo(()=>mockDb.GetStoredProcCommand(Db.SProcs.getfoosbyd)).musthavehaved(Repeated.one);
}

数据库是一个抽象基类,DbProviderFactory也是抽象的,所以您可以模拟它们。只要模拟了对数据库类型调用的操作(几乎所有操作都是虚拟的,所以在那里应该可以),实际上就不需要在提供程序工厂中执行任何操作。连接字符串可以是空的,也可以是null,或者其他任何形式。

我个人加载了源代码,并使用ReSharper提取数据库对象的接口。它重建了,我使用了我的自定义二进制文件。Wala-一个接口!提示:接口很容易模拟。我不知道微软P&P集团为什么不这么做。

FWIW,我能够使用Moq模拟SqlDatabase。SqlDatabase有一个SqlClientPermission属性,该属性在Castle Windsor(Moq使用)中不起作用。我必须明确指示Castle忽略SqlClientPermission属性以使测试正常工作(参见下面示例中的第1行)。下面是一个单元测试示例(借用Steven H的示例)

[TestMethod]
public void FooRepo_CallsCorrectSPOnDatabase()
{
Add(typeof(System.Data.SqlClient.SqlClientPermissionAttribute));
var mockSqlDb=new Mock(“假连接字符串”);
Setup(s=>s.GetStoredProcCommand(“sp_GetFoosById”);
var sut=新的FooRepository(mockSqlDb);
sut.loadfoosbyd(1);
验证(s=>s.GetStoredProcCommand(“sp_GetFoosById”),Times.Once(),“未调用存储过程sp_GetFoosById”);
}

很抱歉我的无知,但是由于您的存储库有一个接口,模拟IFooRepository而不是数据库不是更容易吗?在这个场景中,我需要模拟EntLib数据库实例,以便单独对IFooRepository的实现进行单元测试。
    [TestMethod]
    public void FooRepo_CallsCorrectSPOnDatabase()
    {
        Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(typeof(System.Data.SqlClient.SqlClientPermissionAttribute));
        var mockSqlDb = new Mock<SqlDatabase>("fake connection string");
        mockSqlDb.Setup(s => s.GetStoredProcCommand("sp_GetFoosById"));
        var sut = new FooRepository(mockSqlDb);
        sut.LoadFoosById(1);
        mockSqlDb.Verify(s => s.GetStoredProcCommand("sp_GetFoosById"), Times.Once(), "Stored Procedure sp_GetFoosById was not invoked.");
    }