2013-01-09 7 views
5

Interesuje mnie pisanie testów jednostkowych (przy użyciu NUnit) dla niektórych klas usług utworzonych przy użyciu ServiceStack, przy użyciu "nowego interfejsu API" (dziedziczącego z ServiceStack.ServiceInterface.Service). Właściwość Db usługi jest prawidłowo autoprzewodowa, gdy jest hostowana w aplikacji ASP.NET za pomocą AppHost, ale nie mogę znaleźć odpowiedniej techniki, gdy uruchamiam system poza tym środowiskiem. Widzę różne przestrzenie nazw i klasy związane z testowaniem w ServiceStack, ale nie można znaleźć wyraźnego przykładu, w którym wtłacza się właściwość Db usługi, w przeciwieństwie do prostego konfigurowania fabryki połączeń bezpośrednio, a następnie wywoływania różnych metod rozszerzenia IDbConnection (Insert , Wybierz itd.).Jak wprowadzić Db do klas usług, gdy testowanie jednostki ServiceStack.OrmLite z NUnit?

Próbowałem uwzględniając mój testowy klasy dziedziczą z ServiceStack.ServiceInterface.Testing.TestBase i przesłanianie jego metodę Konfiguruj, aby zarejestrować IDbConnectionFactory (przy użyciu „: pamięci:”), a także ustawienie OrmLiteConfig.DialectProvider = SqliteDialect.Provider; w moim TestFixtureSetUp, ale nadal aby uzyskać wyjątek NullReferenceException podczas wywoływania moich metod serwisowych (at at ServiceStack.ServiceInterface.Service.get_Db()). Wygląda na to, że w kontenerze Funq nie ma nic automatycznego.

Sam SQLite jest poprawnie skonfigurowany, co mogę potwierdzić za pomocą prostszych testów jednostkowych, które pomijają moje klasy usług i po prostu wykonują bezpośrednie wywołania IDbConnection.

Czego mi brakuje?

Edit

Wydaje się, że usługi jednostka testowanie ServiceStack wymaga istnienia hostem a klientem, chociaż wygląda na to, istnieją sposoby, aby ustawić to aby uniknąć kosztów serializacji (używając DirectServiceClient, jak pokazano here) - chociaż nie udało mi się tego zrobić w moim przypadku. Udało mi się to zrobić przy użyciu podejścia AppHostHttpListenerBase (patrz here), chociaż jest to bardziej test integracyjny niż jednostkowy (i jest odpowiednio wolniejszy).

Odpowiedz

5

The docs on Testing pokazuje kilka różnych podejść do wstrzykiwania zależności.

Jeśli spojrzeć na realizację na bazie Service to właśnie tworzy Db z IDbConnectionFactory:

private IDbConnection db; 
public virtual IDbConnection Db 
{ 
    get { return db ?? (db = TryResolve<IDbConnectionFactory>().OpenDbConnection()); } 
} 

że po prostu usuwa z lokalnego lub globalnego IResolver MKOl pojemnika:

public static IResolver GlobalResolver { get; set; } 

private IResolver resolver; 
public virtual IResolver GetResolver() 
{ 
    return resolver ?? GlobalResolver; 
} 

public virtual T TryResolve<T>() 
{ 
    return this.GetResolver() == null 
     ? default(T) 
     : this.GetResolver().TryResolve<T>(); 
} 

Aby wstrzyknąć własne zależności (w przypadku korzystania z usługi klasy bazowej Service) wystarczy skonfigurować IAppHost z zależnościami ces potrzebują które można zrobić z:

using (var appHost = new BasicAppHost { 
    ConfigureContainer = c => { 
     c.Register<IDbConnectionFactory>(new ...); 
    } 
}.Init()) 
{ 
    //...  
} 

które można ustawić na usługi wraz z wszelkimi własnych zależności potrzeb serwisowych, np:

var service = appHost.ResolveService<MyService>(); 

Które autowire wszystkie zależności skonfigurowane Twój AppHost, możesz również dodać własne zależności specyficzne dla testu adhoc poprzez normalny dostęp do własności, np.g:

var service.MyDependency = new Mock<IMyDependency>().Object; 

Odtąd można po prostu zadzwonić i sprawdzić swoje metody klasy C# jak zwykle:

var response = service.Get(new RequestDto { ... }); 
Assert.That(response.Result, Is.Equal("Expected Result from DB")); 
+0

To działało idealnie! Dzięki! Musiałem przekonwertować jeden z moich ExpectedExceptions z powrotem na wewnętrzny (HttpError) z opakowania (WebServiceException), ale ma to sens, biorąc pod uwagę, że już nie przechodzę przez klienta usługi. –

Powiązane problemy