在 rebus 和关联问题中对 Saga 处理程序进行单元测试
Unit testing of Saga handlers in rebus and correlation issues
我在 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 测试 saga:
[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
中包含作为最后一个元素的错误:Could not find existing saga data for message Event2/b91d161b-eb1b-419d-9576-2c13cd9d9c51.
这个 GUID 是什么?和我单元测试定义的完全不一样?有任何想法吗?我尝试测试的内容是否合法(因为我使用的是内存总线)?
此行错误:this.Data.Id = message.MyObjectId.Id
。如果您在覆盖之前检查了 Data.Id
的值,您会注意到 属性 已经有了一个值。
您不分配 saga ID - Rebus 负责。你应该单独留下 属性 :)
关于您的错误 - 当 Rebus 想要记录有关特定消息的信息时,它会记录类型的短名称和消息 ID,即 automatically-assigned rbs2-msg-id
header。换句话说:这不是 属性 m.MyObjectId.Id
的值,您看到的是消息 ID。
由于 saga fixture 对于每个测试 运行 都是 re-initialized,并且您只向它传递一个 Event2
(不允许启动新实例),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 测试 saga:
[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
中包含作为最后一个元素的错误:Could not find existing saga data for message Event2/b91d161b-eb1b-419d-9576-2c13cd9d9c51.
这个 GUID 是什么?和我单元测试定义的完全不一样?有任何想法吗?我尝试测试的内容是否合法(因为我使用的是内存总线)?
此行错误:this.Data.Id = message.MyObjectId.Id
。如果您在覆盖之前检查了 Data.Id
的值,您会注意到 属性 已经有了一个值。
您不分配 saga ID - Rebus 负责。你应该单独留下 属性 :)
关于您的错误 - 当 Rebus 想要记录有关特定消息的信息时,它会记录类型的短名称和消息 ID,即 automatically-assigned rbs2-msg-id
header。换句话说:这不是 属性 m.MyObjectId.Id
的值,您看到的是消息 ID。
由于 saga fixture 对于每个测试 运行 都是 re-initialized,并且您只向它传递一个 Event2
(不允许启动新实例),saga不会被击中。