【问题标题】:Dependency injection of IActorStateManager in Azure Service Fabric stateful actorAzure Service Fabric 有状态 Actor 中 IActorStateManager 的依赖注入
【发布时间】:2016-08-29 02:37:46
【问题描述】:

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

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

这样你就可以在MyService的单元测试中模拟IStateManager

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

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

有什么办法可以解决这个问题还是有其他解决方案?

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 很高兴听到它正在处理中。您提出的解决方案正是我现在实施的。
    • 这个已经实现了吗?
    【解决方案2】:

    我通常在单独的类中编写参与者业务逻辑,该类具有带有 IStateManager 参数的构造函数并实现我的参与者接口。 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 实现。

    【讨论】:

      猜你喜欢
      • 2017-01-31
      • 2018-09-16
      • 1970-01-01
      • 2017-04-18
      • 2017-07-14
      • 2017-07-11
      • 2016-02-16
      • 2017-07-19
      • 2017-06-22
      相关资源
      最近更新 更多