2013-01-09 7 views
5

Ich interessiere mich für Komponententests (mit NUnit) für einige Service-Klassen, die mit ServiceStack erstellt wurden, mit der "New API" (erben von ServiceStack.ServiceInterface.Service). Die Db-Eigenschaft der Dienste wird ordnungsgemäß automatisch verkabelt, wenn sie in einer ASP.NET-Anwendung gehostet wird, die AppHost verwendet, aber ich kann scheinbar nicht die richtige Technik herausfinden, wenn ich außerhalb dieser Umgebung arbeite. Ich sehe in ServiceStack eine Reihe testspezifischer Namespaces und Klassen, kann jedoch kein eindeutiges Beispiel dafür finden, wo die Db-Eigenschaft eines Services injiziert wird, anstatt einfach eine Verbindungsfactory direkt einzurichten und dann die verschiedenen IDbConnection-Erweiterungsmethoden (Insert) aufzurufen , Auswählen usw.).Wie injiziere ich Db in Service-Klassen beim Testen von ServiceStack.Ormlite mit NUnit?

ich versucht habe, aus ServiceStack.ServiceInterface.Testing.TestBase meine Testklasse erben und mit Überschreiben seine Configure-Methode eine IDbConnectionFactory (mit „: memory:“) zu registrieren, sowie OrmLiteConfig.DialectProvider = SqliteDialect.Provider; in meinem TestFixtureSetUp Einstellung, aber ich weiter eine NullReferenceException beim Aufrufen meiner Dienstmethoden abrufen (at at ServiceStack.ServiceInterface.Service.get_Db()). Es scheint, dass der Funq-Container nichts automatisch verkabelt.

SQLite selbst ist ordnungsgemäß eingerichtet, was ich mit einfacheren Komponententests bestätigen kann, die meine Serviceklassen umgehen und einfach IDbConnection-Aufrufe ausführen.

Was fehlt mir?

bearbeiten

es, dass ServiceStack Dienste Komponententests erscheint erfordert die Existenz eines Host und einem Client, obwohl es wie es aussieht Möglichkeiten, dies einzurichten, um die Serialisierung Kosten zu vermeiden (die DirectServiceClient verwenden, wie gezeigt here) - obwohl es mir nicht gelungen ist, das in meinem Fall zu funktionieren. Ich habe es geschafft, dies mit einem AppHostHttpListenerBase-Ansatz (siehe here) arbeiten zu lassen, obwohl es eher ein Integrationstest als ein Unit-Test ist (und dementsprechend langsamer ist).

Antwort

5

Die docs on Testing zeigt ein paar verschiedene Ansätze zum Injizieren von Abhängigkeiten.

Wenn Sie bei der Implementierung für die Basis aussehen Service es schafft nur die Db vom IDbConnectionFactory:

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

Dass es löst nur aus dem lokalen oder globalen IResolver IOC-Container:

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>(); 
} 

So injizieren Sie Ihre eigenen Abhängigkeiten (bei der Verwendung von Service-Basisklasse) müssen Sie nur eine IAppHost mit Ihren Abhängigkeiten Ihre servi konfigurieren ces müssen, was Sie tun können, mit:

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

die Sie auf Ihrem Service dann einstellen können zusammen mit irgendwelchen Ihrer eigenen Abhängigkeiten Ihre Service-Bedürfnisse, zB:

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

Welche werden alle Abhängigkeiten autowire konfiguriert Ihr AppHost können Sie auch Ihre eigenen Adhoc-testspezifischen Abhängigkeiten über den normalen Eigenschaftenzugriff hinzufügen, z.g:

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

Fortan Sie gerade anrufen und Ihre C# Klassenmethoden wie gewohnt testen:

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

Das funktionierte perfekt! Vielen Dank! Ich musste eine meiner ExpectedExceptions aus dem Wrapper (WebServiceException) zurück in die innere (HttpError) konvertieren, aber das macht Sinn, da ich nicht mehr durch einen Service-Client gehe. –