2016-11-21 98 views
1

我想測試我的類,它調用第三方Web服務。這是否可以使用FakeItEasy?FakeItEasy假WCF服務調用

Wenn我試着從Reference.cs(自動生成)僞造類,UnitTest開始並且不回來。

Reference.cs(自動生成)

[System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
    public partial class ws_AccessoryClient : System.ServiceModel.ClientBase<AccessoryService.ws_Accessory>, 
     AccessoryService.ws_Accessory 
    { 
     public ws_AccessoryClient() 
     { 
     } 

     public ws_AccessoryClient(string endpointConfigurationName) : 
      base(endpointConfigurationName) 
     { 
     } 

     public AccessoryService.ResponseMessageOf_ListOf_SomeMethodInfo SomeMethod(
      AccessoryService.RequestMessageOf_SomeMethod request) 
     { 
      return base.Channel.SomeMethod(request); 
     } 
    } 

test.cs中

[Test] 
    public void DoBusinessLogicTryTest() 
    { 
     var accessoryProxy = A.Fake<ws_AccessoryClient>(); 
    } 
+0

一般而言,僞造類(而不是接口)可以是棘手的,因爲所產生的假具有調用原始類的非虛擬行爲。也許這就是這裏發生的事情。考慮調試測試,然後「全部中斷」以查看其卡住的位置。那麼也許我們可以根據我們所學的知識找到更好的答案。 –

回答

2

你不能(和你爲什麼會想?)。

如果要驗證被測試的類是否調用服務,則將該服務調用包裝在只調用該服務的類中,並使用一個接口進行定義。

interface ICallTheService 
{ 
    void CallTheService(); 
} 

class ServiceCaller : ICallTheService 
{ 
    void CallTheService() 
    { 
     // Call the service... 
    } 
} 

然後你就可以僞造這個類,並驗證被測類調用CallTheService操作。

// fake the service caller and pass it into your service 
var serviceCaller = A.Fake<ICallTheService>(); 

// Verify invocation 
A.CallTo(() => serviceCaller.CallTheService()).MustHaveHappened(); 

我想測試我班上的邏輯,依賴於從 的WCF服務

響應這是我覺得你有關注點分離腳麻。您的測試稱爲DoBusinessLogicTryTest,但它依賴於System.ServiceModel,這是一個基礎結構問題。您的業​​務邏輯應該是可測試的,而不依賴於此。如果被測類需要不同的表現取決於響應,你可以做這樣的事情:

interface ICallTheService 
{ 
    ServiceResponseModel CallTheService(); 
} 

enum ServiceResponseModel 
{ 
    Success, 
    PartialSuccess, 
    FailureCondition1, 
    FailureCondition2, 
    // etc... 
} 

然後你可以素ICallTheService假返回每個可能的響應和測試在此基礎上你的課。

A.CallTo(() => serviceCaller.CallTheService()).Returns(ServiceResponseModel.Success); 

例如,如果一些例外(WCF中的定義)的處理方式正確

這也是無關的業務邏輯。實際處理異常是ICallTheService實施的責任。事實上,我會爲此介紹另一個類,它的工作是將various possible exceptions從System.ServiceModel轉換爲您的響應模型。例如,

class WCFErrorResponseTranslator 
{ 
    ServiceResponseModel TranslateWCFException (Exception ex) 
    { 
     if (ex.GetType() == typeOf(TimeoutException)) { return ServiceResponseModel.TimeOut; } 
     /// etc 
    } 
} 

然後可以單獨測試此行爲。

+0

我想測試我的類中的邏輯,取決於來自WCF服務的響應。例如,如果一些異常(定義在WCF中)處理正確。 Endpoint(System.ServiceModel.Description.ServiceEndpoint)也在Class中設置,並且在測試中僞造。謝謝。 –

+0

@AnnyIgi請參閱我的答案更新。 –

+0

謝謝!我會試試看! –

3

如前所述,您可能不想做單元測試的目的,因爲這會導致比使用模擬接口的單元測試所需的噪聲更多的噪聲。然而,它是集成測試的有效方法,這將允許您測試WCF佈線是否按照您的預期工作。它也允許你測試你的應用程序的整體,如果你正在採取一種更行爲驅動的測試方式,你想盡可能少地模擬。

我自己使用這種方法來使用我的博客Hosting a Mock as a WCF service中涵蓋的NSubstitute來旋轉假端點。你需要做的主要事情是旋轉了一個ServiceHost,給它要使用,設置情境模式單一,並提供你想要的端點使用模擬的端點地址。

var serviceHost = new ServiceHost(mock, new[] { baseAddress }); 

serviceHost.Description.Behaviors 
    .Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true; 
serviceHost.Description.Behaviors 
    .Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single; 

serviceHost.AddServiceEndpoint(typeof(TMock), new BasicHttpBinding(), endpointAddress); 

有一兩件事,我在我的測試做的是隨機選擇,我上所託管的端點和測試過程中注入的地址到我的應用程序的端口。這樣,您的測試將能夠在其他機器上運行並構建服務器,而不會與其他正在使用的端口發生衝突。

看你的例子後,你可能要考慮使用WCF ChannelFactory爲您的客戶,而不是使用一個具體的代理客戶端類。 ChannelFactory使用您提供的接口即時創建代理,並允許您使用服務接口將代理注入到它的依賴項中。這將使單元測試更容易,併爲您提供更多解耦設計。

+0

完全同意渠道工廠而不是服務參考 –