我正在构建集成测试,我正在使用InMemNetwork来运行测试。
在断言之前有一个Thread.Sleep调用,但这是一种狡猾的测试方式,它会大大减慢我们的测试速度。
我也在使用SagaFixtures和一个同步运行的简单IBus实现进行一些集成测试,但是注册处理程序,运行处理程序和延迟消息都很乏味。
有没有办法等待Rebus使用的所有线程,直到它们完成执行而不使用ManualResetEvent(在Rebus自己的测试中使用)来增加生产代码?
答案 0 :(得分:0)
我通常使用SagaFixture
,然后使用FakeBus
注入传奇处理程序以捕获他们的行为。
我的大多数测试都是简单处理程序的单元测试,但我会经常注入“真正的”服务,例如实现IThis
和IThat
转到真实数据库。
对于几个场景,虽然我使用内存传输来启动多个端点,然后我通常在InMemNetwork
上实现一个扩展,帮助我等待发布特定事件或类似事件 - 它在测试中看起来像这样:
var updated = await Network.WaitForNext<WhateverUpdated>(subscriberAddress, timeoutSeconds: 20);
其中WaitForNext
只是一个扩展方法,它会轮询subscriberAddress
为下一条消息指定的队列,并尝试将其反序列化为WhateverUpdated
。
我希望能给你一些灵感:)
答案 1 :(得分:0)
对于某些场景,我使用以下方法等待Rebus完成所有消息处理。 rebus端点托管在单独的exe中,rebus文件系统传输用于集成测试(通常是Azure SB)。集成测试旋转了exe,并且在每个exe中,Rebus配置了0个worker,所以它什么也没做。然后在测试中我们有一个WaitForMessagesProcessed()方法,它配置了许多工作者和块,直到没有更多的消息要处理。
以下是代码中粗略显示的内容:
public class MessageProcessor() {
private string queueName;
private int messagesWaitingForProcessing;
private IBus bus;
public MessageProcessor(string queueName) {
this.queueName = queueName;
this.bus = Configure.With(adapter)
.Transport(t => t.UseFileSystem(@"c:\baseDirectory", this.queueName))
.Options(o =>
{
o.SetNumberOfWorkers(0);
})
.Events(e =>
{
e.BeforeMessageSent += (thebus, headers, message, context) =>
{
// When sending to itself, the message is not queued on the network.
var m = context.Load<Rebus.Pipeline.Send.DestinationAddresses>();
if (m.Any(t => t == this.queueName))
this.messagesWaitingForProcessing++;
};
e.AfterMessageHandled += (thebus, headers, message, context, args) =>
{
this.messagesWaitingForProcessing--;
};
})
.Start();
}
public async Task WaitForMessagesProcessed()
{
this.DetermineMessagesWaitingForProcessing();
while (this.messagesWaitingForProcessing > 0)
{
this.bus.Advanced.Workers.SetNumberOfWorkers(2);
while (this.messagesWaitingForProcessing > 0)
{
await Task.Delay(100);
}
this.bus.Advanced.Workers.SetNumberOfWorkers(0);
this.DetermineMessagesWaitingForProcessing();
}
}
public void DetermineMessagesWaitingForProcessing() {
this.messagesWaitingForProcessing = Directory.GetFiles(GetDirectoryForQueueNamed(this.queueName), "*.rebusmessage.json").Count();
}
private static string GetDirectoryForQueueNamed(string queueName)
{
return Path.Combine(this.baseDiretory, queueName);
}
}
测试可能就像
[TestMethod]
public void Test() {
var endpoint1 = LaunchExe("1");
var endpoint2 = LaunchExe("2");
endPoint1.DoSomeAction();
endPoint1.WaitForMessagesProcessed();
Assert.AreEqual("expectation", endPoint1.Query());
}