2012-03-06 11 views
8

Za chwilę rozpoczniemy projektowanie architektury zorientowanej na usługi (SOA), która z pewnością będzie obejmować dużą liczbę szczegółowych usług sieciowych (REST w WCF). Zostaliśmy dość zdyscyplinowani w testowaniu jednostkowej bazy klienckiej i kodowej po stronie serwera, jednak nie mamy dużego doświadczenia w testowaniu usług sieciowych. Naprawdę szukamy wskazówek, gdzie powinny być napisane testy i zalecenia dotyczące tego, jakie podejście zastosować, gdy jednostka testuje nasze usługi.Zalecane wzorce do testowania serwisów sieciowych

Czy powinniśmy pisać testy, które sprawiają, że żądania http i twierdzą, że odpowiedzi są tym, czym powinny być? Czy powinniśmy skupić się tylko na testowaniu wewnętrznej logiki samych metod serwisowych i nie martwić się testowaniem rzeczywistych żądań? Czy powinniśmy zrobić jedno i drugie? Czy są jakieś inne zalecenia dotyczące tego, co powinniśmy testować?

Naprawdę szukamy wyjaśnień i wskazówek i naprawdę doceniamy wszelkie porady, które możemy uzyskać.

Odpowiedz

11

Znalazłem usługi testowania internetowych, konkretnie klienta WCF i serwer, przydatne na górze regularnych testów jednostkowych w następujących scenariuszach:

  1. testowania odbiorczego, w którym chcesz czarnej skrzynki przetestować całą swoją usługę i kłuć rzeczy w kończynach.
  2. Testowanie określonego przewodu WCF, rozszerzenie, zachowanie itp.
  3. Testowanie poprawności konfiguracji interfejsu i elementów danych.

W większości przypadków próbuję użyć bardzo prostej konfiguracji z podstawowym protokołem http i połączyć wszystko w kodzie. O ile nie jestem integratorem ani testem akceptacyjnym, nie testuję klienta na serwerze, zamiast tego kpię z jednego z nich, aby móc przetestować drugi w izolacji. Poniżej przedstawiono przykłady, jak przetestować klientów i usług 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(); 
    } 
} 

UWAGA

ja zapomniałem wspomnieć, że jeśli chcesz, aby drwić usług WCF za pomocą czegoś, który używa zamków dynamicznego proxy następnie będzie musisz uniemożliwić skopiowanie ServiceContractAttribute do wersji próbnej. Mam na to blog post, ale w zasadzie rejestrujesz atrybut jako jeden, aby zapobiec replikacji przed utworzeniem makiety.

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

W gruncie rzeczy myślę, że trzeba mieć strategię testów dwuczęściowych.

Pierwsza część byłaby prawdziwym testem jednostkowym, który obejmowałby testowanie klas całkowicie niezależnych od żądania internetowego ... jako że główna definicja testu jednostkowego to taka, która działa bez potrzeby dodatkowych środowisk lub konfiguracji innych niż te w samym teście.

Aby utworzyć projekty testów jednostkowych, w których można utworzyć instancje klas kodu usług WCF, aby upewnić się, że logika jest poprawna, podobnie jak w przypadku pozostałych klas.

Druga część byłaby zbiorem testów integracyjnych, które testowałyby twoją aplikację w sposób od końca do końca. Oczywiście tutaj potrzebna jest cała enchilada, serwer WWW, baza danych i tak dalej.

W ten sposób wiesz, że twoja logika jest dokładna, a także, że aplikacja działa.