在Azure Service Fabric有状态角色

时间:2016-05-03 21:15:36

标签: dependency-injection actor azure-service-fabric

对于Azure Service Fabric状态服务,可以按如下方式注入IReliableStateManager

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

通过这种方式,您可以在IStateManager的单元测试中模拟MyService

对于有状态的演员来说,这似乎是不可能的。 IActorStateManager只有一个内部实施:Microsoft.ServiceFabric.Actors.Runtime.ActorStateManager。那么我如何对一个有状态的演员进行单元测试?

在我的actor方法的某个时刻,调用IActorStateManager,但由于我无法注入此依赖项,因此单元测试似乎不可能。

有没有办法解决这个问题还是有另一种解决方案?

2 个答案:

答案 0 :(得分:3)

不,IActorStateManager今天不能注射,但我们正在努力做到这一点。现在(不使用反射)你必须将你的状态操作包装在你可以注入的东西中,并将该调用调用到状态管理器中,然后你可以模拟它进行单元测试。

答案 1 :(得分:0)

我通常在具有IStateManager参数的构造函数的单独类中编写actor业务逻辑并实现我的actor接口。 Actor只是在actor实现类中包装,我测试的是actorImpl类而不是actor。看一下代码:

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"]);
    }
}

如果需要,我可以共享StubStateManager实现。