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

时间:2016-11-03 11:10:55

标签: c# unit-testing nservicebus

我在我们的一个服务中遇到了一些代码:

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是否已发布并抛出异常?

3 个答案:

答案 0 :(得分:2)

只需在try catch中包含对Test()的调用,然后对异常进行断言。根据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
    ...
}

答案 1 :(得分:1)

如果您使用NUnit TestFramework,您还可以使用属性来测试预期的异常

import Tkinter as tk

class GCanvas(tk.Canvas, object):

    def __init__(self, master, **kwargs):
        tk.Canvas.__init__(self, master, kwargs)

    @staticmethod
    def enter(e):
        print "enter", e.widget, e.x, e.y

    @staticmethod
    def leave(e):
        print "leave", e.widget

    @staticmethod
    def motion(e):
        print "motion", e.widget, e.x, e.y

approach = "bindinstance"

root = tk.Tk()
gc = GCanvas(root, width=400, height=300)
print "root is", root, "gc is", gc
gc.pack()

if approach == "bindGCanvas":
    print "binding to GCanvas"
    root.bind_class(GCanvas, '<Enter>', GCanvas.enter)
    root.bind_class(GCanvas, '<Leave>', GCanvas.leave)
    #root.bind_class(GCanvas, '<Motion>', GCanvas.motion)
elif approach == "bindCanvas":
    print "binding to Canvas"
    root.bind_class(tk.Canvas, '<Enter>', GCanvas.enter)
    root.bind_class(tk.Canvas, '<Leave>', GCanvas.leave)
    #root.bind_class(tk.Canvas, '<Motion>', GCanvas.motion)
elif approach == "bindinstance":
    print "binding to instance"
    gc.bind('<Enter>', GCanvas.enter)
    gc.bind('<Leave>', GCanvas.leave)
    #gc.bind('<Motion>', GCanvas.motion)
else:
    print "binding to root"
    root.bind('<Enter>', GCanvas.enter)
    root.bind('<Leave>', GCanvas.leave)
    #root.bind('<Motion>', GCanvas.motion)

root.mainloop()

或者如果你更喜欢使用fluent assertions,你也可以使用它并检查抛出异常的确切类型或仅检查基本异常,并进行进一步检查,以获得具有InnerException,Message,...的示例。

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

答案 2 :(得分:1)

如果处理程序抛出异常,则不会检查期望值。要测试这个,你可以向处理程序引入一个布尔标志,并将测试分成两个测试。即。

[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或发件箱配置传输,则在处理程序中抛出异常时,此事件将不会发布(除非发布配置为立即调度)。