首页 > 解决方案 > 如何将依赖项注入 MassTransitStateMachine 活动?

问题描述

我被困住了,lib 的码头没有帮助。鉴于以下传奇定义:

public class GetOrdersStateMachine : MassTransitStateMachine<GetOrdersState>
{
    public State? FetchingOrdersAndItems { get; private set; }

    public Event<GetOrders>? GetOrdersIntegrationEventReceived { get; private set; }

    public GetOrdersStateMachine()
    {
        Initially(
            When(GetOrdersIntegrationEventReceived)
                .Activity(AddAccountIdToState)
                .TransitionTo(FetchingOrdersAndItems));
    }

    private EventActivityBinder<GetOrdersState, GetOrders> AddAccountIdToState(
        IStateMachineActivitySelector<GetOrdersState, GetOrders> sel) =>
        sel.OfType<AddAccountIdToStateActivity>();
}

以及以下活动定义:

public class AddAccountIdToStateActivity : Activity<GetOrdersState, GetOrders>
{
    private readonly IPartnerService _partnerService;

    public AddAccountIdToStateActivity(IPartnerService partnerService) => _partnerService = partnerService;

    public void Probe(ProbeContext context) => 
        context.CreateScope($"GetOrders{nameof(AddAccountIdToStateActivity)}");

    public void Accept(StateMachineVisitor visitor) => visitor.Visit(this);

    public async Task Execute(
        BehaviorContext<GetOrdersState, GetOrders> context,
        Behavior<GetOrdersState, GetOrders> next)
    {
        context.Instance.AccountId = await _partnerService.GetAccountId(context.Data.PartnerId);

        await next.Execute(context);
    }

    public Task Faulted<TException>(
        BehaviorExceptionContext<GetOrdersState, GetOrders, TException> context,
        Behavior<GetOrdersState, GetOrders> next) where TException : Exception => 
        next.Faulted(context);
}

以及下面的测试定义:

var machine = new GetOrdersStateMachine();
var harness = new InMemoryTestHarness();
var sagaHarness = harness.StateMachineSaga<GetOrdersState, GetOrdersStateMachine>(machine);
var @event = new GetOrders("1", new[] {MarketplaceCode.De}, DateTime.UtcNow);

await harness.Start();

try
{
    await harness.Bus.Publish(@event);
    await harness.Bus.Publish<ListOrdersErrorResponseReceived>(new
    {
        @event.CorrelationId,
        AmazonError = "test"
    });

    var errorMessages = sagaHarness.Consumed.Select<ListOrdersErrorResponseReceived>().ToList();
    var sagaResult = harness.Published.Select<AmazonOrdersReceived>().ToList();
    var state = sagaHarness.Sagas.Contains(@event.CorrelationId);

    harness.Consumed.Select<GetOrders>().Any().Should().BeTrue();
    sagaHarness.Consumed.Select<GetOrders>().Any().Should().BeTrue();
    harness.Consumed.Select<ListOrdersErrorResponseReceived>().Any().Should().BeTrue();
    errorMessages.Any().Should().BeTrue();
    sagaResult.First().Context.Message.IsFaulted.Should().BeTrue();
    errorMessages.First().Context.Message.CorrelationId.Should().Be(@event.CorrelationId);
    errorMessages.First().Context.Message.AmazonError.Should().Be("test");
    state.IsFaulted.Should().BeTrue();
}
finally
{
    await harness.Stop();
}

如您所见,AddAccountToStateActivity依赖于IPartnerService. 我想不出一种方法来配置该依赖项。文档中没有任何内容,我也无法在 github 上找到任何内容。我该怎么做?

标签: c#unit-testingmasstransit

解决方案


感谢图书馆的一位作者的帮助,我最终编写了这段代码:

private static (InMemoryTestHarness harness, IStateMachineSagaTestHarness<GetOrdersState, GetOrdersStateMachine> sagaHarness) ConfigureAndGetHarnesses()
{
    var provider = new ServiceCollection()
        .AddMassTransitInMemoryTestHarness(cfg =>
        {
            cfg.AddSagaStateMachine<GetOrdersStateMachine, GetOrdersState>().InMemoryRepository();
            cfg.AddSagaStateMachineTestHarness<GetOrdersStateMachine, GetOrdersState>();
        })
        .AddLogging()
        .AddSingleton(Mock.Of<IPartnerService>())
        .AddSingleton(Mock.Of<IStorage>())
        .BuildServiceProvider(true);
    var harness = provider.GetRequiredService<InMemoryTestHarness>();
    var sagaHarness = provider
        .GetRequiredService<IStateMachineSagaTestHarness<GetOrdersState, GetOrdersStateMachine>>();
    
    return (harness, sagaHarness);
}

如您所见,我正在使用ServiceProvider.


推荐阅读