2016-05-03 7 views
4

Für einen Azure Service-Fabric Stateful Service ist es möglich, die IReliableStateManager zu injizieren, wie folgt:Dependency Injection von IActorStateManager in Azure Service-Fabric Stateful Schauspieler

ServiceRuntime.RegisterServiceAsync("MyServiceType", context => 
{ 
    IReliableStateManager stateManager = new ReliableStateManager(context); 
    return new MyService(stateManager); 
} 

Und auf diese Weise können Sie IStateManager in Unit-Tests für verspotten MyService.

Das gleiche scheint für einen statusstarken Schauspieler nicht möglich. IActorStateManager hat nur eine interne Implementierung: Microsoft.ServiceFabric.Actors.Runtime.ActorStateManager. Wie teste ich einen statusabhängigen Schauspieler?

Irgendwann in meinem Actor-Methoden wird ein Anruf an IActorStateManager gemacht, aber da ich diese Abhängigkeit nicht injizieren kann, scheinen Unit-Tests unmöglich.

Gibt es einen Weg, um dies zu umgehen oder gibt es eine andere Lösung?

Antwort

2

Nein, IActorStateManager ist heute nicht injizierbar, aber wir arbeiten daran, es so zu machen. Fürs Erste (ohne Reflektion zu verwenden) müssen Sie Ihre Statusoperationen in etwas einfügen, das Sie injizieren können, und diesen Aufruf in den Zustandsmanager laden, den Sie dann für Unit-Tests vortäuschen können.

+1

Gut zu hören, dass daran gearbeitet wird. Die Lösung, die Sie vorschlagen, ist genau das, was ich jetzt implementiert habe. –

0

Normalerweise schreibe ich Akteur Geschäftslogik in separate Klasse, die Konstruktor mit IStateManager Parameter und implementieren meine Actor-Schnittstelle. Actor ist nur Wrapper um Actor-Implementierungsklasse und ich teste die actorImpl-Klasse statt des Actors. Sehen Sie sich den Code an:

public interface IMyActor01 : IActor 
{ 
    Task<int> GetCountAsync(); 
    Task SetCountAsync(int count); 
} 

public class MyActor01Impl : IMyActor01 
{ 
    private readonly IActorStateManager StateManager; 

    public MyActor01Impl(IActorStateManager stateManager) 
    { 
     this.StateManager = stateManager; 
     this.StateManager.TryAddStateAsync("count", 0); 
    } 

    public Task<int> GetCountAsync() 
    { 
     return this.StateManager.GetStateAsync<int>("count"); 
    } 

    public Task SetCountAsync(int count) 
    { 
     return this.StateManager.AddOrUpdateStateAsync("count", count, (key, value) => count > value ? count : value); 
    } 
} 

[StatePersistence(StatePersistence.Persisted)] 
internal class MyActor01 : Actor, IMyActor01 
{ 
    private MyActor01Impl Impl; 

    protected override Task OnActivateAsync() 
    { 
     ActorEventSource.Current.ActorMessage(this, "Actor activated."); 
     this.Impl = new MyActor01Impl(this.StateManager); 
     return Task.FromResult(true); 
    } 

    Task<int> IMyActor01.GetCountAsync() 
    { 
     return this.Impl.GetCountAsync(); 
    } 

    Task IMyActor01.SetCountAsync(int count) 
    { 
     return this.Impl.SetCountAsync(count); 
    } 
} 

[TestFixture] 
public class TestFixture01 
{ 
    [Test] 
    public void Test01() 
    { 
     //ARRANGE 
     var dictionary = new Dictionary<string, object>(); 
     var impl = new MyActor01Impl(new StubStateManager(dictionary)); 

     //ACT 
     impl.SetCountAsync(12).Wait(); 

     //ASSERT 
     Assert.AreEquals(12, impl.GetCountAsync().Result); 
     //or 
     Assert.AreEquals(12, (int)dictionary["count"]); 
    } 
} 

Ich kann StubStateManager-Implementierung teilen, wenn Sie möchten.