NServiceBus:测试事件已发布并且同时抛出异常

NServiceBus: Testing that event is published AND exception is thrown at the same time

我 运行 在我们的一项服务中查看了一些代码,如下所示:

try
{
    // Step 1: collect underpants.
}
catch (Exception ex)
{
    // If this is the last retry we'll raise an event.
    if (Bus.IsLastRetry())
    {
        PublishFailedEvent(ex);
    }

    // But we'll also send the error to the error queue no matter what.
    throw;
}

还有一个看起来像这样的测试:

Test.Handler(bus => new Processor() { Bus = bus })
    .ExpectPublish<IFailedEvent>()
    .OnMessage<ISomeHappenedEvent>();

因为我们在发布测试失败后立即抛出。有没有办法测试 FailedEvent 是否已发布并且异常是否已抛出?

只需将对 Test() 的调用包装在 try catch 中,然后针对异常进行断言。根据 NSB 的版本,处理程序可能会引发 TargetInvocationException,您需要询问该异常以获取内部异常。

try
{
    Test.Handler(bus => new Processor() { Bus = bus }).OnMessage<ISomeHappenedEvent>();
}
catch (MyExpectedException ex)
{
    // Asserts 
    ...
}

或者,

try
{
    Test.Handler(bus => new Processor() { Bus = bus }).OnMessage<ISomeHappenedEvent>();
}
catch (TargetInvocationException ex)
{
    // Asserts against ex.InnerException
    ...
}

如果你使用NUnit TestFramework你也可以使用属性来测试预期的异常

[Test]
    [ExpectedException(typeof(MyException))]
    public void it_should_throw_attribute()
    {
        Assert.Fail();
    }

或者如果您更喜欢使用 fluent assertions,您也可以使用它并检查抛出异常的确切类型或仅检查基本异常并进行进一步检查,例如包含 InnerException、Message、...

[Test]
    public void it_should_throw_exactly()
    {
        Action actionToTest = () => { throw new MyException(); };
        actionToTest.ShouldThrowExactly<MyException>();
    }

    [Test]
    public void it_should_throw()
    {
        Action actionToTest = () => { throw new MyException(); };
        actionToTest.ShouldThrow<Exception>();
    }

如果处理程序抛出异常,则不会检查预期。要对此进行测试,您可以向处理程序引入一个布尔标志并将测试拆分为两个测试。即

[Test]
public void it_should_publish_event()
{
    Test.Handler(bus => new Processor() { Bus = bus, DoNotThrow = true })
        .ExpectPublish<IFailedEvent>()
        .OnMessage<ISomeHappenedEvent>();
}

[Test, ExpectedException(typeof(YourException))]
public void it_should_throw()
{
    Test.Handler(bus => new Processor() { Bus = bus })
        .OnMessage<ISomeHappenedEvent>();
}

请注意,如果传输是使用 DTC 或发件箱配置的,那么如果处理程序中抛出异常,则不会发布此事件(除非发布配置为立即分派)。