gpt4 book ai didi

c# - 使用 NServiceBus 在应用程序中测试 Bus.Send

转载 作者:太空狗 更新时间:2023-10-29 21:42:01 25 4
gpt4 key购买 nike

我在我的应用程序 .NET 应用程序中使用 NServiceBus 有这段代码:

 Bus.Send<IServiceStarted>(e =>
{
e.ServiceInfo = ReadServiceInfo();
e.EventTime = DateProvider.Now;
});

您将如何对这样的代码进行单元测试?

最佳答案

只要您的 Bus 变量是一个 IBus 实例,您就可以简单地向包含此方法的类提供模拟的 IBus 实现,并验证在调用该方法进行测试后是否调用了 Send(如果需要,可以使用适当的委托(delegate))。除此之外,您将开始测试 Bus.Send 本身,这不是您应该做的事情。

public class ClassThatSendsMessages
{
private readonly IBus _bus;
public ClassThatSendsMessages(IBus bus /*, ... */)
{
_bus = bus;
/* ... */
}

public void CodeThatSendsMessage()
{
/* ... */
_bus.Send<IMyMessage>(mm => mm.Property1 = "123");
/* ... */
}
}

public class ClassThatTestsClassThatSendsMessages
{
public void CallCodeThatSendsMessage()
{
//Mock IBus object here
var objectToTest = new ClassThatSendsMessages(mockedIBus /*, ... */)

objectToTest.CodeThatSendsMessage();

//Verify that IBus mock's Send() method was called
}
}

有两种方法可以测试委托(delegate)的逻辑:您可以尝试分解提供的表达式树,或者您可以将其更改为命名方法并以此方式传递。我从未深入研究过表达式,因此我将提供后者的示例:

public static class MyMessageBuilder
{
public static void Build(IMyMessage message) { /* ... */ }
}

public class ClassThatTestsMyMessageBuilder
{
public void CallCodeThatBuildsMessage()
{
var message = Test.CreateInstance<IMyMessage>(MyMessageBuilder.Build);

//Verify message contents
}
}

用法:

public class ClassThatSendsMessages
{
private readonly IBus _bus;
public static Action<IMyMessage> BuildMessage { private get; set; }
public ClassThatSendsMessages(IBus bus /*, ... */)
{
_bus = bus;
/* ... */
}

public void CodeThatSendsMessage()
{
/* ... */
_bus.Send<IMyMessage>(mm => BuildMessage (mm));
/* ... */
}
}

我不知道可以将委托(delegate)注入(inject)构造函数的容器,但后来我也没有仔细研究,所以这可能是设置委托(delegate)的更好方法。

编辑

因为我最近在我自己的测试中遇到了这个问题,我真的不喜欢将这个方法拉到它自己的构建器中。所以我开始探索是否可以“就地”测试委托(delegate)。事实证明你可以:

public class ClassThatTestsClassThatSendsMessages
{
public void CallCodeThatSendsMessage()
{
Action<IMyMessage> messageAction = null;

//Mock IBus object here
mockedIBus.Setup(b => b.Send(Args.IsAny<Action<IMyMessage>>()))
.Callback((Action<IMyMessage> a) => messageAction = a);
var myMessage = Test.CreateInstance<IMyMessage>();

var objectToTest = new ClassThatSendsMessages(mockedIBus /*, ... */)

//Run the code that sends the message
objectToTest.CodeThatSendsMessage();
//Run the code that populates the message
messageAction(myMessage);

//Verify expectations on Setups
//Verify the message contents;
}
}

这里需要权衡取舍——将消息生成器拉出到一个界面中肯定比将其保留为内联委托(delegate)更符合 SRP(测试清楚地表明:您必须执行两次才能测试所有代码)。但是,它在代码大小和可读性方面都有好处。

此外,代码是特定于 Moq 的;我不知道是否可以从 RhinoMocks 模拟中取回委托(delegate),或者它的语法是什么。

关于c# - 使用 NServiceBus 在应用程序中测试 Bus.Send,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3909055/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com