2014-01-21 94 views
0

我有一個簡單的「Get」方法。例如:單元測試不會「覆蓋」簡單的get方法。 (c#)

public class Foo : IFoo 
{ 
    public Dictionary<string,string> GetSomething(string xyz) 
    { 
     var result = new Dictionary<string,string> 
     ... Go to DB and return some key value pairs 
     return result; 
    } 
} 

我寫了一個簡單的測試,執行並通過成功,但我沒有得到代碼覆蓋的方法。

[TestMethod()] 
    public void GetSomething() 
    { 
     var target = new StubIFoo(); 

     var expected = new Dictionary<string, string> 
     { 
      {"blahKey","blahValue"} 
     }; 

     var results = target.GetSomethingString = s => 
     { 
      var result = new Dictionary<string, string> {{"a", "b"}}; 
      return result; 
     }; 

     var actual = results("a"); 

     CollectionAssert.AreEqual(expected,actual); 
    } 

我也試圖針對類本身,它提供了覆蓋,但不返回任何結果(例如:「VAR目標=新StubFoo();」)

再次,它成功地執行並通過,但我沒有得到任何報道。任何指針將不勝感激。謝謝。

+0

你期待什麼保險? 'StubFoo'和'Foo'之間有什麼關係? – Paolo

+0

你想要測試什麼? 'Foo'還是別的什麼?如果你想測試'Foo',你爲什麼要剔除'GetSomething'? (基本上,你不能期望覆蓋你故意剔除的方法 - 你沒有執行該代碼!) –

+0

顯示你的存根的代碼。 – Haney

回答

0

在您的測試中,您沒有調用方法GetSomething,而是將值設置爲屬性GetSomethingString

// Here is the problem. This: 
var results = target.GetSomethingString = s => 
{ 
    var result = new Dictionary<string, string> {{"a", "b"}}; 
    return result; 
}; 
// Is equal to this: 
var lambda = s => 
{ 
    var result = new Dictionary<string, string> {{"a", "b"}}; 
    return result; 
}; 
var results2 = target.GetSomethingString = lambda; 
+0

我將其改爲原始測試,但它覆蓋了代碼,但實際不會返回任何內容(試圖避免數據庫依賴性)。 var target = new StubFoo(); var expected = new Dictionary { {「a」,「b」} }; var actual = target.GetSomething(「a」); CollectionAssert.AreEqual(expected,actual); – user3219570

2

Foo.GetSomething()的代碼覆蓋率爲0,因爲您從未在測試中調用它。相反,你調用StubIFoo.GetSomething()。

var target = new StubIFoo();更改爲var target = new Foo();,刪除初始化StubIFoo的代碼,您將獲得一些覆蓋範圍。

存根可以防止你使用(和測試)真實的類。但是你不能使用你正在測試的類的存根!

+0

謝謝。我原來是這樣,但無法弄清楚如何刪除數據庫依賴關係。看起來我必須存儲「GetSomething」和「shim」數據庫調用。 – user3219570

+0

如果要刪除數據庫依賴關係,則需要刪除DB類(IDbConnection,IDbCommand ...)或用於您在Foo.GetSomething()方法中使用的數據庫層。例如,您可以使用依賴注入(簡而言之,當您的程序中需要IDbConnection時,它會爲您提供SqlConnection,並且在您的測試中需要IDbConnection時,它會爲您提供StubIDbConnection) – krimog

+0

@ user3219570:您不需要存儲Foo,但填充數據庫調用應該可以工作。不過,這可能很麻煩。你應該做克里莫克所暗示的。 – Magus

0

這是一般的想法,你應該做的

public class Foo : IFoo 
{ 
    IDbAccess db; 

    // Pass the interface, do pass parameters to create it inside constructor 
    public Foo(IDbAccess db) 
    { 
     this.db = db; 
    } 

    public Dictionary<string,string> GetSomething(string xyz) 
    { 
     var result = new Dictionary<string,string> 

     // ... Go to DB and return some key value pairs 
     result.Add(db.MethodWhatever(xyz)); 

     return result; 
    } 
} 

[TestMethod()] 
public void GetSomething() 
{ 
    var dbMock = new DatabaseMock(); // This implements IDbAccess 
    var target = new Foo(dbMock); 

    var expected = new Dictionary<string, string> 
    { 
     {"blahKey","blahValue"} 
    }; 

    // get something 
    var results = target.GetSomething("xyzstring"); 

    // verify results 
    var actual = results.whatever; 

    CollectionAssert.AreEqual(expected,actual); 
} 
+0

嘿詹恩 - 我很欣賞你的時間和快速反應。我不確定我知道如何在不實現所有成員的情況下「存根/模擬」IDbCommand(我假設你的IDbAccess是一個繼承它的接口)。 – user3219570

+0

你不存根/模擬IDbCommand。您只需創建一個接口,以便您可以創建一個模擬對象來充當您的數據庫訪問。就像你的實際的數據庫實例也應該實現保存IDbAccess接口作爲DatabaseMock,它只會返回你將要除外的數據。如果Foo.GetSomething將創建DbCommand並執行它,那麼您需要通過重構來消除依賴性,以便您擁有將實現您需要的dataacceess方法的類。 –