2016-02-18 114 views
2

學習Moq,並需要一些幫助來測試回調結果。結構是:我有一個DateManager對象,它依賴於對服務器進行異步調用的DateServer對象。使用Moq在C中測試回調#

DateServer.GetValidDate將採用yyyy-MM-dd中的日期字符串,並將使用相同格式的字符串執行給定的回調。

如何設置模擬服務器,例如,下面的測試將通過?一個簡單的模擬設置將是我的模擬DateServer將簡單地返回提供給它的任何字符串(在回調中)。

這是我的設置。我認爲我有這個結構的大部分是正確的,但需要幫助填寫?在下面的代碼中。如果我應該更好地測試回調回報,那麼我也對此感興趣。

public interface IDateServer 
{ 
    // with a currencyPair (ie: USDCAD), verifies that the given date is 
    // valid for a potential transaction. 
    // Callback is used to process the returned result, which is a date string. 
    void GetValidDate(string currencyPair, string date, Action<string> callback); 
} 

public interface IDateManager 
{ 
    void GetDate(string currencyPair, string dateCode, Action<string> callback); 
} 

[TestClass] 
public class DateManagerTests 
{ 
    [TestMethod] 
    public void GetDateTest() 
    { 
     ManualResetEvent ar = new ManualResetEvent(false); 

     Mock<IDateServer> server = new Mock<IDateServer>(); 
     DateTime tradeDate = new DateTime(2016, 2, 17); 

     server.Setup(????); 

     IDateManager dm = new DateManager(tradeDate, server); 

     string ret = ""; 
     dm.GetDate("USDCAD", "2016-02-17", (string s) => 
     { 
      ret = s; 
      ar.Set(); 
     }); 

     ar.WaitOne(); 

     Assert.AreEqual<string>(ret, "2016-02-17"); 

    } 

} 

回答

2

如果你想想測試的DateManager,你想確保DateManager調用DateServer依賴與一組特定的參數的GetValidDate方法。該方法不會返回任何內容,因此不需要進行設置。

,作爲調用回調方法是不是被測試的類DataServer,這不是重要的回調是否真的叫。您必須在DateServer的單獨測試中對此進行測試。

因此,下面的測試方法應驗證該DateManager傳遞正確的參數到DateServer(右在這種情況下=被傳遞給DateManager的參數):

[TestMethod] 
public void GetDateTest() 
{ 
    Mock<IDateServer> server = new Mock<IDateServer>(); 
    Action<string> callback = (string s) => { }; 
    IDateManager dm = new DateManager(server.Object); 
    dm.GetDate("USDCAD", "2016-02-17", callback); 
    server.Verify(x => x.GetValidDate("USDCAD", "2016-02-17", callback)); 
} 
+0

所以我們調用'dm.GetDate()',然後'Verify()'檢查GetValidDate()被正確調用。這是有道理的,對於這種情況是最重要的。但是,如果我的DateManager在最後一次回調之前操縱返回的結果,會發生什麼?我仍然想檢查回調中返回的字符串。這個怎麼做? – gdbj

+0

@gdbj AFAIK'DateServer'是應該調用回調的那個。因此,從對DateManager的測試角度來看,不需要檢查回調是否真的被調用。在'DateServer'的單獨測試中,您可以像在示例代碼中那樣向'DateServer'提供虛擬回調(無模擬)。另外,如果'DateManager'在某個時候需要調用回調函數,則會提供一個虛擬回調函數,並檢查這個函數是否被調用了適當的次數。由於調用不能源自模擬的'DateServer',它就是'DateManager'。 – Markus

+0

是的,我現在看到你是對的。任何斷言檢查都不是必需的,因爲結果是由設置自己設計的。花了我一些時間來解決這個問題。 – gdbj

2

這將設置爲GetValidDate回調,將讓您使用傳遞給方法的任何參數時,它被稱爲嘲笑的接口上。

Mock<IDateServer> server = new Mock<IDateServer>(); 

const string testDateString = "2016-02-17"; 
const string testCurrencyPair = "USDCAD"; 

server.Setup(obj => obj.GetValidDate(It.IsAny<string>(), 
            It.IsAny<string>(), 
            It.IsAny<Action<string>>())) 
     .Callback<string, string, Action<string>>((currencyPair, date, callback) => 
     { 
      // The parameters passed into GetValidDate (see below) 
      // will be available in here. 
      Debug.WriteLine(currencyPair); 
      Debug.WriteLine(date); 
     }); 

server.Object.GetValidDate(testCurrencyPair, testDateString, null); 

從我的Callback方法的理解,這樣只會通知你,嘲笑方法實際上是調用,並用什麼參數。

+0

我不知道這對我來說很清楚。我想斷言testDateString匹配回調中返回的內容。 – gdbj

+0

在回調中,用'Assert.AreEqual(testDateString,date)'替換'Debug'調用。 – MotoSV

+0

在回調中指定的參數,即'currencyPair','date'和'callback',將包含任何對'server.Object.GetValidDate'的調用中傳遞的值,即使在DateManager中調用也是如此。 – MotoSV