2012-03-06 88 views
8

我們即將開始構建面向服務的框架(SOA),該框架肯定會涉及大量粒度Web服務(WCF中的REST)。在單元測試我們的客戶端和服務器端代碼庫方面,我們一直非常謹慎,但是我們沒有太多的單元測試Web服務經驗。我們真的在尋找關於應該如何編寫測試的指導,以及在單元測試我們的服務時使用什麼方法的建議。單元測試Web服務的推薦模式

我們應該編寫測試,使http請求和斷言,他們應該是響應?我們是否應該專注於測試服務方法本身的內部邏輯,而不是擔心測試實際的請求?或者我們應該這樣做?對於我們應該測試的內容是否還有其他建議?

我們真的在尋找一些解釋和指導,並會真正感謝我們可以得到的任何建議。

回答

11

我發現測試Web服務,特別是WCF客戶端和服務器,在下列情況下,常規的單元測試的頂部有用:

    要黑箱測試您全程服務,並捅事情
  1. 驗收測試在極端。
  2. 測試特定的WCF連線,擴展,行爲等。
  3. 測試您的接口和數據成員設置是否正確。

大多數情況下,我嘗試使用基本http的基本設置,並將代碼中的所有內容連接起來。除非我是集成或驗收測試,否則我不會在服務器上測試客戶端,而是嘲笑其中的一個,以便我可以單獨測試另一個客戶端。下面是我如何測試WCF客戶端和服務的例子:

public static ServiceHost CreateServiceHost<TServiceToHost>(TServiceToHost serviceToHost, Uri baseAddress, string endpointAddress) 
{ 
    var serviceHost = new ServiceHost(serviceToHost, new[] { baseAddress }); 

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

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

    return serviceHost; 
} 

//Testing Service 

[TestFixture] 
class TestService 
{ 
    private ServiceHost myServiceUnderTestHost; 
    private ChannelFactory<IMyServiceUnderTest> myServiceUnderTestProxyFactory; 
    [SetUp] 
    public void SetUp() 
    { 
     IMyServiceUnderTest myServiceUnderTest = new MyServiceUnderTest(); 
     myServiceUnderTestHost = CreateServiceHost<IMyServiceUnderTest>(myServiceUnderTest, new Uri("http://localhost:12345"), "ServiceEndPoint"); 
     myServiceUnderTestHost.Open(); 

     myServiceUnderTestProxyFactory = new ChannelFactory<IMyServiceUnderTest>(new BasicHttpBinding(), new EndpointAddress("http://localhost:12345/ServiceEndPoint")); 
    } 

    [TearDown] 
    public void TearDown() 
    { 
     myServiceUnderTestProxyFactory.Close(); 
     myServiceUnderTestHost.Close(); 
    } 

    [Test] 
    public void SomeTest() 
    { 
     IMyServiceUnderTest serviceProxy = myServiceUnderTestProxyFactory.CreateChannel(); 

     serviceProxy.SomeMethodCall(); 
    } 
} 

//Testing Client 

[TestFixture] 
class TestService 
{ 
    private ServiceHost myMockedServiceUnderTestHost; 
    private IMyServiceUnderTest myMockedServiceUnderTest; 

    [SetUp] 
    public void SetUp() 
    { 
     myMockedServiceUnderTest = Substitute.For<IMyServiceUnderTest>(); //Using nsubstitute 
     myServiceUnderTestHost = CreateServiceHost<IMyServiceUnderTest>(myMockedServiceUnderTest, new Uri("http://localhost:12345"), "ServiceEndPoint"); 
     myServiceUnderTestHost.Open(); 
    } 

    [TearDown] 
    public void TearDown() 
    { 
     myServiceUnderTestHost.Close(); 
    } 

    [Test] 
    public void SomeTest() 
    { 
     //Create client and invoke methods that will call service 
     //Will need some way of configuring the binding 
     var client = new myClientUnderTest(); 

     client.DoWork(); 

     //Assert that method was called on the server 
     myMockedServiceUnderTest.Recieved().SomeMethodCall(); 
    } 
} 

注意

我已經忘了提,如果你想使用任何使用城堡動態代理則嘲笑一個WCF服務,你會需要防止將ServiceContractAttribute複製到模擬。我有一個blog post對此,但基本上你註冊該屬性爲一個以防止複製,然後再創建模擬。

Castle.DynamicProxy.Generators.AttributesToAvoidReplicating 
    .Add<ServiceContractAttribute>(); 
3

基本上,我認爲你需要有一個兩部分的測試策略。

,第一部分是真正的單元測試,這將涉及測試完全獨立於任何Web請求的類... 作爲單元測試的主要定義是,無需額外的環境或其它設置運行而不是測試本身的那些。

因此,您將創建單元測試項目,其中您將實例化WCF服務的代碼類,以確保邏輯正確,與測試其餘類的方式大致相同。

第二部分是一組集成測試,它將以端到端的方式測試您的應用程序。當然,在這裏你需要整個辣醬玉米餅餡,網絡服務器,數據庫等等。

這樣你就知道你的邏輯是準確的,而且你的應用程序也能正常工作。