2012-04-02 78 views
0

背景:起訂量多接口

我已經剝離了一個簡單的代理事情在線上和部分發現我需要的實例部分基於我的WCF客戶端。

用於創建客戶端代理作爲其公知的用法是:

WcfClientProxy<IServicecontract> clientProxy = 
           new WcfClientProxy<IServiceContract>(); 

WcfClientProxy有一個稱爲執行這需要方法:Expression<Func<TChannel, TResult>>Expression<Action<TChannel>>

我想要實現:

我想嘲笑這起訂量使用,所以我可以測試通過客戶服務合同的呼籲。

所以嘲笑這樣的電話..

clientProxy.Execute(m=>m.DoSomeAction(5)); 

問題:

的問題是,模擬不起作用。我得到這個錯誤:

「拋出異常: System.NullReferenceException:對象引用未設置爲對象的實例。」

我的測試服務合同是:

public interface ITestingServiceInterface : System.ServiceModel.IClientChannel 
{ 
    string Version(); 
    VersionDetail VersionDetail(); 
    IList<VersionDetail> VersionDetails(); 
    void DoSomeDelete(int itemId); 
} 

WCF客戶端代理接口:

public interface IWcfClientProxy<TChannel> where TChannel : ICommunicationObject 
{ 
    bool ThrowOnException { get; set; } 
    TResult Execute<TResult>(Expression<Func<TChannel, TResult>> operation); 
    void Execute(Expression<Action<TChannel>> expression); 
} 

我試圖測試,並與設置模擬..

private List<ProdItem> items; 
private Mock<IWcfClientProxy<ITestingServiceInterface>> mockClientProxy; 

[TestInitialize] 
public void SettingUp() 
{ 
    mockClientProxy = new Mock<IWcfClientProxy<ITestingServiceInterface>>(); 

    items = new List<ProdItem>(); 
    for(int i =0; i<10; i++){ 
     items.Add(new ProdItem { ProdItemId = i, LocalStock = i }); 
    } 
} 

[TestMethod] 
public void SimpleTest() 
{ 
    mockClientProxy.Setup(m => m.Execute(x => x.DoSomeDelete(It.IsAny<int>()))).Callback(RemoveItem); 

    var client = mockClientProxy.Object; 

    client.Execute(x => x.DoSomeDelete(4)); 

    Assert.AreEqual(9, items.Count); 
} 

public void RemoveItem() 
{ 
    items.RemoveAt(items.Count - 1); 
} 

此錯誤測試實際上是斷言是錯誤的,似乎回調從未被擊中。

我確信我剛剛做了一些愚蠢的事情。

更新: 顯示的,我想怎樣能夠測試上述工作的例子..

[TestMethod] 
public void SimpleTest() 
{ 
    mockClientProxy.Setup(m => m.Execute(x => x.DoSomeDelete(It.IsAny<int>()))).Callback(RemoveItem); 

    var client = mockClientProxy.Object; 

    var stockHelper = new StockHelper(client); 

    stockHelper.DeleteItem(5); 

    Assert.AreEqual(9, items.Count); 
} 

在上面,我是測試StockHelper類需要在客戶端代理它的構造函數通過它來調用WCF。

要測試StockHelper(或什麼),我需要能夠模擬客戶端及其服務調用。上面的(第一)例子惡魔 - 直截了當地試圖做到這一點。

我希望這是有道理的,請參閱我的最終目標不是測試模擬..這正是我必須嘗試調試我的問題。

回答

2

正如我從你的代碼可以看出,你正在測試模擬。我沒有看到你正在測試的任何真實物體。 Mock用於存根被測試對象的依賴關係。所以,如果某個類Foo使用IWcfClientProxy那麼你提供這個代理的模擬到Foo類。並驗證在Foo.Bar()執行方法DoSomeDelete的依賴被調用。這就是嘲笑的目的。

[TestClass] 
public class FooTests 
{ 
    private Foo _foo; 
    private Mock<IWcfClientProxy<ITestingServiceInterface>> _clientProxy; 

    [TestInitialize] 
    public void SettingUp() 
    { 
     _clientProxy = new Mock<IWcfClientProxy<ITestingServiceInterface>>(); 
     _foo = new Foo(_clientProxy.Object); 
    } 

    [TestMethod] 
    public void SimpleTest() 
    { 
     // Act on object being tested 
     _foo.Bar(5); 

     // verify it executed correct method on dependency 
     _clientProxy.Verify(cp => cp.Execute(x => x.DoSomeDelete(5))); 
    } 
} 

測試Foo你不應該怎麼在意_clientProxy在執行時記住。

+0

客戶端代理一般會被傳遞到的東西,說一個輔助類。那麼測試就是測試助手類而不是代理,但是因爲我目前還沒有證明這個代理是一個例子。如果我沒有傳遞參數給服務方法,它按預期工作。 – 2012-04-02 10:14:54

+0

我已經更新了這個問題,(剛纔看到您的更新後的答案)我是否需要使用驗證而不是設置退貨和回叫?那會是我的問題嗎? – 2012-04-02 10:24:42

+0

代理具有方法'執行'。所以你需要驗證這個方法是用正確的參數調用的。如果需要,您可以爲模擬方法提供一些假返回值。 (對不起午餐時間,將在一小時內):) – 2012-04-02 10:27:35

0

有你的模擬設置事情很奇怪。我認爲您設置的匹配參數僅限於第一層函數調用。您可能需要做一些事情,如:

mockClientProxy.Setup(m => m.Execute(It.IsAny<Expression<Action<TChannel>>>())).Callback(RemoveItem); 

起訂量的工作原理是實現其參數的接口上的方法,在這種情況下,它的IWcfClientProxy<ITestingServiceInterface>接口方法。因此,當您將方法調用設置爲執行時,您需要爲參數設置匹配參數以執行。你在代碼中做了什麼就是爲該特定的委託函數設置一個匹配項,該函數永遠不會匹配任何內容,因爲你不存儲它並稍後調用Execute。