2010-08-18 139 views
6

是否可以嘲笑企業庫5版本的'數據庫'?如果是這樣......怎麼樣?嘲笑企業庫5'數據庫'

有沒有IDatabase接口(這是一個謎,因爲我雖然微軟P將更多地暴露這種接口暴露測試性的好處)。

我有一個使用EntLib 5數據訪問應用程序塊的Repository類。

我是復古適合單元測試到這個類,並需要嘲笑依賴於數據庫對象。這個類是現在通過其構造函數傳遞數據庫,並使用數據庫對象在Db上執行操作。

我使用以下方法來解決數據庫的實例來傳遞給我的信息庫:

Container.RegisterType<IFooRepository, FooRepository>(
    new InjectionConstructor(
     EnterpriseLibraryContainer.Current.GetInstance<Database>("FooDbConnStr") 
    ) 
); 

我不希望將這些單元測試成爲集成測試。

我已經嘗試過使用Moq創建數據庫類型的動態模擬,但事實證明這很棘手,因爲數據庫在其構造函數中需要連接字符串和DbProviderFactory。也許,如果有這樣的事情,一個MockDbProviderFactory

這是單元測試正在採取以下形式:

EntLib UnitTest Attempt to Mock Database

題外話:我也發現使用一個靜態的Logger類很難測試的。希望我在這裏錯過了一些技巧,但是我必須說我對迄今爲止的可測試性感到失望。

+0

對不起我的無知,但你有一個接口爲您的存儲庫,豈不是更容易嘲笑IFooRepository而不是數據庫? – thiagoleite 2012-07-13 17:24:48

+1

我需要在此場景中模擬EntLib數據庫實例,以便單獨測試IFooRepository的實現。 – holsee 2012-07-17 22:06:07

回答

2

我用FakeItEasy http://code.google.com/p/fakeiteasy/

我創建了一個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); 
} 
1

數據庫是一個抽象基類,而DbProviderFactory也是抽象的,所以你可以把它們都模擬出來。只要你嘲笑你在數據庫類型上調用的操作(幾乎所有的東西都是虛擬的,所以你應該在那裏確定),你實際上並不需要在提供者工廠中做任何事情。連接字符串可以只是空或空或任何其他。

1

我個人裝載了源代碼並使用ReSharper爲數據庫對象提取接口。它重建,我用我的自定義二進制文件。 Wala - 一個界面!提示:接口很容易模擬。爲什麼微軟P組沒有這樣做,我不知道。

+0

我也不是,好主意。 – holsee 2010-12-26 22:09:09

3

FWIW,我能夠使用Moq模擬一個SqlDatabase。 SqlDatabase具有SqlClientPermission屬性,它與Castle Windsor(Moq使用)不兼容。我必須明確指示Castle忽略SqlClientPermission屬性才能使測試正常工作(請參見下面示例中的第1行)。以下是一個樣本單元測試(借用Steven H的例子)。

[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."); 
    }