如何使用ReceiveAsync在Akka.NET actor中测试异步异常

时间:2019-10-22 20:36:36

标签: c# testing xunit akka.net

我的应用程序和单元测试中都有一个try / catch块。我正在尝试创建一个测试,以捕获演员中引发的异常。通过代码调试时,会引发异常,但是在测试中,我从未收到异常。

应用程序:

public class FooActor : ReceiveActor {
    private readonly IFooService fooService;
    private readonly IChildActorFactory childCreatorFactory;
    private IActorRef barActor;

    public FooActor(IFooService fooService, IChildActorFactory childCreatorFactory) {   
        this.fooService = fooService;
        this.childCreatorFactory = childCreatorFactory;

        ReceiveAsync<bool>(async (x) => await StartAsync(x).ConfigureAwait(false));
    }

    protected override void PreStart() {
        barActor = childCreatorFactory.Create<BarActor>(Context, "BarActor");
    }

    public async Task StartAsync(bool start) {
        try {
            if (start) {
                var fooInformation = await fooService.GetInformationAsync().ConfigureAwait(false);

                if (fooInformation != null) {
                    barActor.Tell(fooInformation);
                }
            }
        } catch (Exception exception) {
            throw new Exception($"Unhandled exception. Actor {Self.Path.Name};", exception);
        }
    }
}

测试:

[Fact]
public void StartAsync_ThrowsException_ExceptionThrown() {
    using (var mock = AutoMock.GetLoose()) {
        //Arrange
        Sys.UseAutofac(mock.Container);
        var mockChildActorFactory = mock.Mock<IChildActorFactory>();
        var mockBarService = mock.Mock<IBarService>();

        mockBarService.Setup(x => x.GetInformationAsync()).Throws(new Exception());

        var props = Props.Create(() => new FooActor(mockBarService.Object, mockChildActorFactory.Object));

        var fooActorName = "FooActor";
        var fooActor = new TestActorRef<FooActor>(Sys, props, null, fooActorName);

        try {
            // Act
            fooActor.Receive(true);
        } catch (Exception exception) {
            // Assert
            Assert.Equal($"Unhandled Exception. Actor { fooActorName }.", exception.Message);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

问题出在ReceiveAsync方法中的async / await运算符中:

ReceiveAsync<bool>(async (x) => await StartAsync(x).ConfigureAwait(false));

当执行上下文到达await操作时,它仅在线程池(简化)处启动Task并返回到调用方。即什么时候

fooActor.Receive(true);

已完成,带有StartAsync(x)的实际任务可能尚未开始。因此,当引发实际异常时,您的测试已经完成而没有任何异常。