unit-testing - Saga 处理程序在 rebus 和相关性问题中的单元测试

标签 unit-testing rebus saga

我在 Rebus 中有这个简单的 Saga:

public void MySaga : Saga<MySagaData>
    IAmInitiatedBy<Event1>
    IHandleMessages<Event2>
{
        private IBus bus;
        private ILog logger;

        public MySaga(IBus bus, ILog logger)
        {
            if (bus == null) throw new ArgumentNullException("bus");
            if (logger == null) throw new ArgumentNullException("logger");

            this.bus = bus;
            this.logger = logger;
        }

        protected override void CorrelateMessages(ICorrelationConfig<MySagaData> config)
        {

            config.Correlate<Event>(m => m.MyObjectId.Id, s => s.Id);
            config.Correlate<Event>(m => m.MyObjectId.Id, s => s.Id);
        }

    public Task Handle(Event1 message)
    {
        return Task.Run(() =>
        {
            this.Data.Id = message.MyObjectId.Id;
            this.Data.State = MyEnumSagaData.Step1;
            var cmd = new ResponseCommandToEvent1(message.MyObjectId);
            bus.Send(cmd);
        });
    }

    public Task Handle(Event2 message)
    {
        return Task.Run(() =>
        {
            this.Data.State = MyEnumSagaData.Step2;
            var cmd = new ResponseCommandToEvent2(message.MyObjectId);
            bus.Send(cmd);
        });
    }
}

感谢 mookid8000,我可以使用 FakeBus 和 SagaFixture 来测试传奇:

[TestInitialize]
public void TestInitialize()
{
    var log = new Mock<ILog>();
    bus = new FakeBus();
    fixture = SagaFixture.For<MySaga>(() => new MySaga(bus, log.Object));
    idTest = new MyObjectId(Guid.Parse("1B2E7286-97E5-4978-B5B0-D288D71AD670"));
}

[TestMethod]
public void TestIAmInitiatedBy()
{
    evt = new Event1(idTest);
    fixture.Deliver(evt);
    var testableFixture = fixture.Data.OfType<MySagaData>().First();
    Assert.AreEqual(MyEnumSagaData.Step1, testableFixture.State);
    // ... more asserts
}

[TestMethod]
public void TestIHandleMessages()
{
    evt = new Event2(idTest);
    fixture.Deliver(evt);
    var testableFixture = fixture.Data.OfType<MySagaData>().First();
    Assert.AreEqual(MyEnumSagaData.Step2, testableFixture.State);
    // ... more asserts
}

[TestCleanup]
public void TestCleanup()
{
    fixture.Dispose();
    bus.Dispose();
}

第一个测试方法检查 IAmInitiatedBy 是否正确执行并且没有抛出错误,而第二个测试失败。它看起来像是关联问题,因为 fixture.Data 不包含任何元素,并且在 fixture.LogEvents 中包含最后一个元素此错误:无法找到消息的现有传奇数据事件2/b91d161b-eb1b-419d-9576-2c13cd9d9c51

这个 GUID 是什么?和我在单元测试中定义的完全不同吗?有任何想法吗?我尝试测试的内容合法吗(因为我使用的是内存总线)?

最佳答案

这一行是错误的:this.Data.Id = message.MyObjectId.Id。如果您在覆盖之前检查了 Data.Id 的值,您会注意到该属性已经有一个值。

您不分配 saga ID - Rebus 会这样做。你应该保留该属性:)

关于您的错误 - 当 Rebus 想要记录有关特定消息的信息时,它会记录类型的短名称和消息 ID,即自动分配的 rbs2 的值-msg-id header 。换句话说:您会看到,这不是属性 m.MyObjectId.Id 的值,而是消息 ID。

由于每次测试运行都会重新初始化 saga 夹具,并且您只向其传递 Event2 (不允许启动新实例),因此 saga 不会被命中。

关于unit-testing - Saga 处理程序在 rebus 和相关性问题中的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36018100/

相关文章:

c# - 将事件重新提交到 rebus

.net-core - CQRS 是 saga/process manager 同步执行一组相关命令的最佳方法吗?

nservicebus - 在 NServiceBus 中,当消息传入而没有匹配的传奇时,我该如何处理?

unit-testing - 如果 TDD 用于单元,测试怎么会意外地先通过(作为一个错误)?

java - 在参数化 JUnit 测试到来时执行大量参数化测试,而不是在它们全部可用时执行

c# - 使用 Mocks 验证依赖调用时的 TDD Arrange Act Assert 模式

c# - Rebus 失败的消息会发生什么情况

messaging - 我应该如何为一个生产者和许多消费者设置 rebus

rest - 微服务 Saga 模式消费者等待响应

ios - 在 prepare for segue 方法中初始化 ViewController 是一个好习惯吗?