C# 使用NserviceBus。测试当代码未通过消息处理程序启动时,如何测试已发布事件
问题 如果正在测试的当前方法是通过传入消息(进入处理程序)以外的其他方法启动的,那么如何测试事件的发布。NServiceBus.Testing(据我所知)的问题在于它非常适合于测试处理程序,而这些处理程序又会导致消息/事件被发送/发布 背景: 我们有许多遗留系统,在向适当的SOA实现过渡的过程中,我们需要与一些遗留数据库作业集成。这些作业每15分钟在数据库上执行一次操作,我们希望在某些情况发生时将这些操作挂接到并发布事件 我们有一个在NsbHost中运行的windows服务,但不包含任何处理程序。相反,我们使用Quartz创建一个内部cron作业,该作业每分钟运行一次,轮询DB以查找与指定模式匹配的记录,并在更新DB之前发布一个事件,以表明我们已经处理了该记录。这就是我们整合新旧系统的方式 显然,这不是一个理想的情况,但考虑到我们正处于SOA实现的过渡阶段,它和我们现在的情况一样好 详细信息和代码: 我们正在发布的事件界面如下所示C# 使用NserviceBus。测试当代码未通过消息处理程序启动时,如何测试已发布事件,c#,.net,unit-testing,moq,nservicebus,C#,.net,Unit Testing,Moq,Nservicebus,问题 如果正在测试的当前方法是通过传入消息(进入处理程序)以外的其他方法启动的,那么如何测试事件的发布。NServiceBus.Testing(据我所知)的问题在于它非常适合于测试处理程序,而这些处理程序又会导致消息/事件被发送/发布 背景: 我们有许多遗留系统,在向适当的SOA实现过渡的过程中,我们需要与一些遗留数据库作业集成。这些作业每15分钟在数据库上执行一次操作,我们希望在某些情况发生时将这些操作挂接到并发布事件 我们有一个在NsbHost中运行的windows服务,但不包含任何处理程序
public interface IPremiumAdjustmentFinalised
{
string PolicyNumber { get; set; }
decimal Amount { get; set; }
DateTime FinalisedOn { get; set; }
}
var myBus = new myBus();
eventPublisher = new AdjustmentFinaliserEventPublisher(myBus);
eventPublisher.UpdateAndPublishFinalisedAdjustments();
实际发布事件的代码是
Bus.Publish<IPremiumAdjustmentFinalised>(e =>
{
e.Amount = AdjustmentAmount;
e.PolicyNumber = PolicyNumber;
e.FinalisedOn = LastModifiedOn;
});
Bus.Publish(e=>
{
e、 金额=调整金额;
e、 保单编号=保单编号;
e、 finalizedon=LastModifiedOn;
});
这一切都很好,我们可以使用MOQ测试调用,因此:
eventPublisher.MethodToTest();
bus.Verify(x => x.Publish(It.IsAny<Action<IPremiumAdjustmentFinalised>>()), Times.Once);
eventPublisher.MethodToTest();
bus.Verify(x=>x.Publish(It.IsAny()),Times.one);
其中,总线是插入到构造函数中的新模拟
但我想测试ipremiumadjustmentfinalized中的值。我发现这非常困难,我想主要是因为它是一个接口,而不是一个具体的类
我们已经尝试使用NServiceBus.Testing来尝试和检查生成的事件,但没有效果
有人知道如何在给定场景中测试事件中的值吗?我们提出了两种解决方案 解决方案1: 创建一个继承接口的具体类,并发布该类
public class PremiumAdjustmentFinalisedEvent : IPremiumAdjustmentFinalised
{
public string PolicyNumber { get; set; }
public decimal Amount { get; set; }
public DateTime FinalisedOn { get; set; }
}
此类仅在发送方中使用,另一端的处理程序仍将侦听类型为IPREMIUMADJUSTMENTFinalized的事件
发送事件将更改为
var message = new PremiumAdjustmentFinalisedEvent
{
Amount = AdjustmentAmount,
PolicyNumber = PolicyNumber,
FinalisedOn = LastModifiedOn
};
Bus.Publish<IPremiumAdjustmentFinalised>(message);
我喜欢这个解决方案,因为它不会仅仅为了测试而更改实时代码,但缺点是IBus的大量实现中包含大量未实现的方法。在找到这篇文章后,在谷歌搜索结果周围搜索了几天之后,除了这篇文章之外,似乎没有其他真正的指导。在实现了解决方案2之后,我决定找到一种更轻松的方法,并提出了以下使用Moq作为模拟库的方法
///Declarations
private Mock<IPremiumAdjustmentFinalised > _mockEvent = new Mock<IPremiumAdjustmentFinalised >();
private readonly Mock<IBus> _mockBus = new Mock<IBus>();
private SomeEventPublisher _someEventPublisher;
[SetUp]
public void Setup()
{
//Instruct moq to set up implementations for the event interface's properties.
_mockEvent.SetupAllProperties();
_mockBus.Setup(b => b.Publish(It.IsAny<Action<IPremiumAdjustmentFinalised>>()))
.Callback((Action<IPremiumAdjustmentFinalised> messageConstructor) =>
{
//Execute the constructor provided in the action in the event publisher, so the event data can be interrogated.
messageConstructor(_mockEvent.Object);
});
_someEventPublisher = new SomeEventPublisher(_mockBus);
}
[Test]
public void SomeEventPublisherTest()
{
_someEventPublisher.PublishSomeEvent(AdjustmentAmount, LastModifiedOn, PolicyNumber)
Assert.AreEqual(_mockEvent.Object.Amount, AdjustmentAmount);
Assert.AreEqual(_mockEvent.Object.FinalisedOn, LastModifiedOn);
Assert.AreEqual(_mockEvent.Object.PolicyNumber, PolicyNumber);
}
///声明
私有模拟_mockEvent=new Mock();
私有只读Mock_mockBus=new Mock();
私有SomeEventPublisher\u SomeEventPublisher;
[设置]
公共作废设置()
{
//指示moq为事件接口的属性设置实现。
_mockEvent.SetupAllProperties();
_mockBus.Setup(b=>b.Publish(It.IsAny()))
.Callback((操作消息构造函数)=>
{
//执行事件发布程序中操作中提供的构造函数,以便查询事件数据。
messageConstructor(_mockEvent.Object);
});
_someEventPublisher=新的someEventPublisher(_mockBus);
}
[测试]
public void SomeEventPublisherTest()
{
_someEventPublisher.PublishSomeEvent(AdjustmentAmount、LastModifiedOn、PolicyNumber)
Assert.AreEqual(_mockEvent.Object.Amount,AdjustmentAmount);
Assert.AreEqual(_mockEvent.Object.finalizedon,LastModifiedOn);
Assert.AreEqual(_mockEvent.Object.PolicyNumber,PolicyNumber);
}
var myBus = new myBus();
eventPublisher = new AdjustmentFinaliserEventPublisher(myBus);
eventPublisher.UpdateAndPublishFinalisedAdjustments();
///Declarations
private Mock<IPremiumAdjustmentFinalised > _mockEvent = new Mock<IPremiumAdjustmentFinalised >();
private readonly Mock<IBus> _mockBus = new Mock<IBus>();
private SomeEventPublisher _someEventPublisher;
[SetUp]
public void Setup()
{
//Instruct moq to set up implementations for the event interface's properties.
_mockEvent.SetupAllProperties();
_mockBus.Setup(b => b.Publish(It.IsAny<Action<IPremiumAdjustmentFinalised>>()))
.Callback((Action<IPremiumAdjustmentFinalised> messageConstructor) =>
{
//Execute the constructor provided in the action in the event publisher, so the event data can be interrogated.
messageConstructor(_mockEvent.Object);
});
_someEventPublisher = new SomeEventPublisher(_mockBus);
}
[Test]
public void SomeEventPublisherTest()
{
_someEventPublisher.PublishSomeEvent(AdjustmentAmount, LastModifiedOn, PolicyNumber)
Assert.AreEqual(_mockEvent.Object.Amount, AdjustmentAmount);
Assert.AreEqual(_mockEvent.Object.FinalisedOn, LastModifiedOn);
Assert.AreEqual(_mockEvent.Object.PolicyNumber, PolicyNumber);
}