2015-11-15 10 views
16

Ich kann einen zuverlässigen Service/Actor nicht testen, indem ich einfach seinen Konstruktor aufrufen und dann seine Methoden testen. var testService = new SomeService(); löst eine NullReferenceException aus. Also, was kann ich mit entfalteten Service tun ..Service-Fabric-Unit-Test und Abhängigkeitsinjektion

Ich verstehe, dass die bereitgestellten SF Reliable Services/Actors sind nicht Standard-.NET-Klassen, und Unit-Tests von bereitgestellten S/A vielleicht eine seltsame Idee.

Wie auch immer, jetzt versuche ich es zu versuchen.

Zum Beispiel. Ich habe gerade einen Service bereitgestellt, als im Test habe ich ein Proxy-Objekt erstellt und Element in die Eingangswarteschlange von Service hinzugefügt. Dann muss ich behaupten, dass Eingangswarteschlange = 1 ist. Und es funktioniert, wenn ich gerade einen Dienst bereitgestellt habe und keine anderen Klienten/Dienste/Schauspieler seine Eingangswarteschlange benutzt haben. Aber das nächste Mal, wenn dieser Test fehlschlägt, ist das das Problem. Ich muss den Dienst dazu bringen, nicht mehr mit anderen Verbrauchern zu arbeiten, seine Warteschlange fallen zu lassen und sie dann zu testen. Zu diesem Zweck kann ich eine TestMode-Eigenschaft und einige Methoden wie PropareoForTests/TestingCompleted erstellen und sie vor und nach dem Test vom Test-Client aufrufen.

Ist das eine schlechte Idee, es so zu machen? Vielleicht gibt es einige Richtlinien für Unit-Tests SF? Vielen Dank.

UPDATE:

Während Service Fabric Web Reference Application example Untersuchung habe ich diese TODO Zeichenfolge gefunden:

/// TODO: Temporary property-injection for an IServiceProxyWrapper until constructor injection is available. 

Bedeutet es, dass SF Dienstleistungen es ist DI-Unterstützung verbessern? Was ist mit Schauspielern?

+3

Constructor Abhängigkeitsinjektion ist tatsächlich jetzt in den Akteuren verfügbar! Wenn Sie Ihren Akteurstyp registrieren, können Sie auch eine "Fabrik" registrieren, die eigentlich nur ein Func <> ist, wo Sie Ihre Actor-Klasseninstanz erstellen, wodurch Sie die Instanziierung Ihres Actors steuern können, um Abhängigkeiten durch dort zu injizieren. In Diensten können Sie dies bereits tun, überprüfen Sie, wie wir es im Party-Cluster-Beispiel tun: https://github.com/Azure-Samples/service-fabric-dotnet-management-party-cluster/tree/master/PartyCluster/ ClusterService –

+1

Ich schrieb eine Antwort auf die Abhängigkeit Injektion mit Einheit: http://stackoverflow.com/questions/30384780/azure-service-fabric-actor-dependency-injection/35900027#35900027 –

+0

@VaclavTurecek Ihr Link ist gebrochen – Dismissile

Antwort

16

Eigentlich können Sie Reliable Services und Actors genauso testen, wie Sie eine andere Klasse in .NET testen würden! Sie sind nur insofern besonders, als sie bestimmte Hooks in der zugrunde liegenden Plattform verwenden, aber ansonsten können Sie Ihren Dienst oder Ihre Akteursklasse normal instanziieren und Methoden aufrufen.

Derzeit sind Reliable Services etwas einfacher zu testen, da der primäre Hook in der Plattform, der State Manager, eine Schnittstelle ist, die über den Konstruktor eingesteckt werden kann.

Zum Beispiel Ihrer Service-Klasse könnte wie folgt aussehen:

EDIT: Aktualisiert mit dem GA-Release-API (2.0.135)

class MyService : StatefulService 
{ 
    public MyService (StatefulServiceContext context, IReliableStateManager stateManager) 
     :base (context, stateManager) 
    { 
    } 

    public void MyMethod() 
    { 
    // do stuff.. 
    } 
} 

Dann können Sie Ihre Service-Klasse testen, wie so:

[TestMethod] 
public TestMyMethod() 
{ 
    MockReliableStateManager stateManager = new MockReliableStateManager(); 
    MyService target = new MyService(stateManager); 

    target.MyMethod(); 
    // validate results and all that good stuff 
} 

Wir haben ein komplettes Arbeitsbeispiel tatsächlichen Leistungen mit vielen Abhängigkeiten Einheit auf GitHub verfügbar getestet: https://github.com/Azure-Samples/service-fabric-dotnet-management-party-cluster

Dieses Beispiel enthält auch IRielableStateManager- und IReliableDictionary-Mocks, die Sie als Ausgangspunkt für Ihre eigenen Komponententests verwenden können.

+0

Danke, Vaclav! Dies ist genau das, was benötigt wird. Bitte sehen Sie sich das Update an. – AsValeO

+1

In der RTM (Actors 2.0.135) ist die 'Actor.StateManager' -Eigenschaft schreibgeschützt (keine' protected set'). Wie sollte ich die Statusmanagerabhängigkeit für meine Akteursklasse injizieren? –

+0

Und was ist mit Erinnerungen und Timern für Schauspieler? Ich kann die 'ReceiveReminderAsync'-Methode selbst aufrufen, aber ich muss die Aufrufe von 'RegisterReminderAsync' (geschützte Methode auf' ActorBase') überprüfen. –

4

für den Staat Manager in Zuverlässiger Schauspieler spöttisch, können Sie etwas tun:

private readonly IActorStateManager _stateManager; 

public MyActor(IActorStateManager stateManager = null) 
{ 
    _stateManager = stateManager ?? this.StateManager; 
} 

Eigentlich ist die StateManager noch nicht zu diesem Zeitpunkt initialisiert. Wir können es bekommen, wenn OnActivateAsync genannt wird:

private IActorStateManager _stateManager; 

// Unit tests can inject mock here. 
public MyActor(IActorStateManager stateManager = null) 
{ 
    _stateManager = stateManager; 
} 

protected override async Task OnActivateAsync() 
{ 
    if (_stateManager == null) 
    { 
     _stateManager = StateManager; 
    } 
} 

So stellen Sie sicher immer _stateManager des Codes in den Rest zu verwenden, anstatt this.StateManager.