2015-11-15 15 views
16

Non riesco a testare un servizio/attore affidabile semplicemente chiamando il suo costruttore e testando i suoi metodi. var testService = new SomeService(); genera una eccezione NullReferenceException. Quindi, cosa posso fare con il servizio distribuito.Service Fabric Injection Testing and Dependency Injection

Capisco che gli SF Reliable Services/Actors implementati non siano classi .NET standard, e il test di unità di S/A schierato potrebbe essere una strana idea.

Ad ogni modo sto provando a fare un tentativo.

Ad esempio. Ho appena distribuito un servizio, che nel test ho creato un oggetto Proxy e aggiunto elementi nella coda di input del servizio. Quindi devo affermare che il conteggio della coda di input = 1. E funziona se ho appena distribuito un servizio e nessun altro client/servizio/attore ha utilizzato la coda di input. Ma la prossima volta che questo test fallirà questo è il problema. Ho bisogno di fare in modo che il Servizio smetta di funzionare con altri utenti, di rilasciarlo e di testarlo. A tale scopo posso creare alcune proprietà TestMode e alcuni metodi come PropareoForTests/TestingCompleted e chiamarli dal client di test prima e dopo il test.

È una cattiva idea farlo in quel modo. Forse ci sono delle linee guida per i test unitari di SF? Grazie.

UPDATE:

Mentre indaga Service Fabric Web Reference Application example ho trovato questa stringa TODO:

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

Vuol dire che SF servizi migliorerà sia il supporto DI? E gli attori?

+3

L'iniezione della dipendenza del costruttore è attualmente disponibile negli attori! Quando registri il tuo tipo di attore, puoi anche registrare un "factory" che in realtà è solo un Func <> dove crei la tua istanza della classe Actor, che ti dà il controllo sull'istanza del tuo attore in modo da poter iniettare le dipendenze da lì. Nei servizi puoi già farlo, guarda come lo facciamo nell'esempio del Cluster di partito: https://github.com/Azure-Samples/service-fabric-dotnet-management-party-cluster/tree/master/PartyCluster/ ClusterService –

+1

Ho scritto una risposta sull'iniezione di dipendenza con unità: http://stackoverflow.com/questions/30384780/azure-service-fabric-actor-dependency-injection/35900027#35900027 –

+0

@VaclavTurecek il tuo link è rotto – Dismissile

risposta

16

In realtà è possibile testare Servizi e Attori affidabili nello stesso modo in cui testare qualsiasi altra classe in .NET! Sono speciali solo perché usano determinati hook nella piattaforma sottostante, ma a parte questo puoi istanziare normalmente la tua classe di servizio o attore e chiamare i metodi su di essa.

Attualmente, i servizi affidabili sono un po 'più facili da testare l'unità perché il gancio principale nella piattaforma, lo State Manager, è un'interfaccia che si può collegare tramite il costruttore.

Ad esempio, la classe di servizio potrebbe essere simile a questo:

EDIT: aggiornato con l'API versione GA (2.0.135)

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

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

Quindi è possibile verificare la classe di servizio in questo modo:

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

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

Abbiamo un esempio di lavoro completa di servizi effettivi con un sacco di dipendenze che sono unità di testate disponibili su GitHub: https://github.com/Azure-Samples/service-fabric-dotnet-management-party-cluster

Questo esempio ha anche IReliableStateManager e IReliableDictionary e può essere utilizzato come punto di partenza per i propri test di unità.

+0

Grazie, Vaclav! Questo è esattamente ciò che è necessario. Si prega di dare un'occhiata all'aggiornamento. – AsValeO

+1

In RTM (Actors 2.0.135), la proprietà 'Actor.StateManager' è di sola lettura (nessun' set protetto'). Come devo iniettare la dipendenza dello stato manager per la mia classe di attore? –

+0

E i promemoria e i timer per gli attori? Posso chiamare da solo il metodo 'ReceiveReminderAsync', ma ho bisogno di verificare le chiamate fatte a' RegisterReminderAsync' (metodo protetto su 'ActorBase'). –

4

Per beffardo il manager stato nel Attori affidabili, si può fare qualcosa di simile:

private readonly IActorStateManager _stateManager; 

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

In realtà, il StateManager non è ancora inizializzato in questo momento. Siamo in grado di farlo quando OnActivateAsync si chiama:

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

Basta fare in modo di utilizzare sempre _stateManager nel resto del codice, invece di this.StateManager.