如何测试自动命名状态机?

时间:2018-06-22 15:12:02

标签: c# testing masstransit automatonymous

我正在尝试为自动机状态机编写测试,但是在正确设置它方面遇到了很多麻烦,而且我发现的文档很少。

这是我目前要进行的一项测试:

[TestFixture]
public class MyProcessStateMachineTests
{
    InMemoryTestHarness _Harness;
    MyProcessStateMachine _Machine;
    StateMachineSagaTestHarness<MyProcess, MyProcessStateMachine> _Saga;

    [OneTimeSetUp]
    public void ConfigureMessages()
    {
        MessageCorrelation.UseCorrelationId<RequestMyDetails>(x => x.CorrelationId);
        MessageCorrelation.UseCorrelationId<FileAttached>(x => x.CorrelationId);
        MessageCorrelation.UseCorrelationId<PDFGenerated>(x => x.CorrelationId);
        MessageCorrelation.UseCorrelationId<CustomerAttachFile>(x => x.CorrelationId);
        MessageCorrelation.UseCorrelationId<AddCustomerNote>(x => x.CorrelationId);
        MessageCorrelation.UseCorrelationId<EmailPublished>(x => x.CorrelationId);
    }


    [SetUp]
    public void InitializeTestHarness()
    {
        _Harness = new InMemoryTestHarness();
        _Machine = new MyProcessStateMachine( /* snip */ );
        _Saga = _Harness.StateMachineSaga<MyProcess, MyProcessStateMachine>(_Machine);

        _Harness.Start().Wait();
    }

    [TearDown]
    public void StopTestHarness()
    {
        _Harness.Stop();
    }


    [Test]
    public async Task ShouldAttachToCustomer()
    {
        var sagaId = Guid.NewGuid();
        var custId = Guid.NewGuid();
        var fileAttached = BuildFileAttachedMessage(sagaId);

        await _Harness.InputQueueSendEndpoint.Send(BuildStartMessage(sagaId));
        await _Harness.InputQueueSendEndpoint.Send(BuildDetailsReceivedMessage(sagaId));
        await _Harness.InputQueueSendEndpoint.Send(BuildPdfGeneratedMessage(sagaId));
        await _Harness.InputQueueSendEndpoint.Send(fileAttached);

        // Next line is based on [the answer here][1]
        // Once the above messages are all consumed and processed,
        // the state machine should be in AwaitingEmail state
        await _Saga.Match(x =>
            x.CorrelationId == sagaId
                && x.CurrentState == _Machine.AwaitingEmail.Name,
            new TimeSpan(0, 0, 30));

        // Grab the instance and Assert stuff...
    }

    // Snip...
}

鉴于_Saga.Match调用找到了匹配项,所以我希望所有消息都已处理,并且我应该能够获取我的状态机实例和已发布的事件并检查其值-事实并非如此。当我在固定装置中运行测试时,有时我得到的实例已经消耗并发布了预期的消息。有时还不在那里。

我尝试使用以下方法获取实例:

var inst = _Saga.Sagas.FirstOrDefault(x => x.Saga.CorrelationId == sagaId);

或通过以下方式获取已发布的事件:

var test = _Harness.Published
    .FirstOrDefault(x => x.MessageType == typeof(IAttachFile) && x.Context.CorrelationId == sagaId);

,但是对Match的调用成功并不重要,状态机实例(和已发布的事件)并不总是存在。

我假设来自Automatonymous,MassTransit或测试工具的异步处理导致了不一致。有帮助吗?

使用MassTransit,MassTransit.Automatonymous和MassTransit.TestFramework 5.1.2.1528,Automatonymous 4.1.1.102,进行测试

编辑:

进一步检查,我发现遇到问题时,可以致电Match( ... ) 没有成功-超时。 (我一直错误地认为超时会引发异常。)

1 个答案:

答案 0 :(得分:0)

对于遇到相同问题的任何人:您尝试获取实例的方式

var inst = _Saga.Sagas.FirstOrDefault(x => x.Saga.CorrelationId == sagaId);

可以这样固定

var instanceIds = await _sagaHarness.Match(
    instance => instance.CorrelationId == sagaId
        && instance.CurrentState == _machine.Working.Name,
        new TimeSpan(0, 0, 30));

在条件中包括预期状态很重要。仅仅通过correlationidid获取实例,然后测试CurrentState可能会失败,因为设置状态(异步执行传奇)可能需要一些时间。 请参见https://github.com/balintn22/AutomatonymousTestExample

的完整示例