MassTransit.RequestFaultException:’message’ 请求发生故障:无法访问已释放的对象

huangapple go评论76阅读模式
英文:

MassTransit.RequestFaultException : The 'message' request faulted: Cannot access a disposed object

问题

I have two micro services with rabbitmq and masstransit v8 latest version that I send request from micro A to micro B and get data from database then response the result.
In application every thing work great but in integration test with inmemorytestharness I get this error MassTransit.RequestFaultException : The EventBus.Messages.Contracts.Services.Discounts.Currencies.Query.GetCurrencyByName.GetCurrencyByNameRequest request faulted: Cannot access a disposed object.

Message for request:

public class GetCurrencyByNameRequest
{
    public string Name { get; set; }
}

Message for response:

public class GetCurrencyByNameResponse
{
    public string Id { get; set; } 
    public string Name { get; set; } 
}

Consumer:

public class GetCurrencyByNameConsumer : IConsumer<GetCurrencyByNameRequest>
{
    private readonly IUnitOfWork _uow;

    public GetCurrencyByNameConsumer(IUnitOfWork uow)
    {
        _uow = uow;
    }
    public async Task Consume(ConsumeContext<GetCurrencyByNameRequest> context)
    {
        var filter = Builders<Currency>.Filter.Eq(x => x.CurrencyName, new CurrencyName(context.Message.Name));
        var currency = await _uow.GenericRepository<Currency>()
            .GetSingleDocumentByFilterAsync(filter, context.CancellationToken);
        if (currency == null)
        {
            await context.RespondAsync(new GetCurrencyByNameResponse
            {
                Id = string.Empty,
                Name = string.Empty
            });
        }
        else
        {
            await context.RespondAsync(new GetCurrencyByNameResponse
            {
                Id = currency.Id,
                Name = currency.CurrencyName
            });
        }
    }
}

Masstransit configuration in micro A:

   services.AddMassTransit(x =>
        {
            var entryAssembly = AppDomain.CurrentDomain.GetAssemblies()
                .FirstOrDefault(x => x.FullName.Contains("Payment.Application"));
            x.SetKebabCaseEndpointNameFormatter();
            x.AddConsumers(entryAssembly);
            x.UsingRabbitMq((context, cfg) =>
            {
                //cfg.Host(new Uri(configuration["RabbitMqSettings:Uri"]));
                cfg.Host(configuration["RabbitMqSettings:Host"], configuration["RabbitMqSettings:VirtualHost"], h =>
                {
                    h.Username(configuration["RabbitMqSettings:Username"]);
                    h.Password(configuration["RabbitMqSettings:Password"]);
                });
                cfg.UseDelayedRedelivery(r => r.Intervals(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(30)));
                cfg.UseMessageRetry(r => r.Immediate(5));
                cfg.UseInMemoryOutbox();
                cfg.ConfigureEndpoints(context);
            });
        });

Masstransit configuration in micro B:

  services.AddMassTransit(x =>
        {
            var entryAssembly = AppDomain.CurrentDomain.GetAssemblies()
                .FirstOrDefault(x => x.FullName.Contains("Discount.Application"));
            x.SetKebabCaseEndpointNameFormatter();
            x.AddConsumers(entryAssembly);
            x.UsingRabbitMq((context, cfg) =>
            {
               // cfg.Host(new Uri(configuration["RabbitMqSettings:Uri"]));
                cfg.Host(configuration["RabbitMqSettings:Host"], configuration["RabbitMqSettings:VirtualHost"], h =>
                {
                    h.Username(configuration["RabbitMqSettings:Username"]);
                    h.Password(configuration["RabbitMqSettings:Password"]);
                });
                cfg.UseDelayedRedelivery(r => r.Intervals(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(30)));
                cfg.UseMessageRetry(r => r.Immediate(5));
                cfg.UseInMemoryOutbox();
                cfg.ConfigureEndpoints(context);
            });
        });

Masstransit inmemorytestharness configuration:

 public static InMemoryTestHarness TestHarness { get; set; } = default!;
    public static IBus TestHarnessBus { get; set; } = default!;
    public static async Task UseHarnessAsync()
    {
        await using var provider = new ServiceCollection()
                .AddScoped<IUnitOfWork, UnitOfWork>()
              

                .AddMassTransitInMemoryTestHarness(x =>
                        {
                            x.SetKebabCaseEndpointNameFormatter();
                            x.AddConsumer<GetCurrencyByNameConsumer>();
                            //                      .Endpoint(x=>x.Name = "get-currency-by-name-request");

                            x.AddConsumerTestHarness<GetCurrencyByNameConsumer>();
                           
                        })

                .AddGenericRequestClient()
                .BuildServiceProvider(true);

        TestHarness = provider.GetRequiredService<InMemoryTestHarness>();
        await TestHarness.Start().ConfigureAwait(false); 
        TestHarnessBus = provider.GetRequiredService<IBus>();

    }

IntegrationTest:

    [Test]
    public async Task CreatePackageCommand_InsertToDb_ReturnPackage()
    {
        IRequestClient<GetCurrencyByNameRequest>? client = TestHarnessBus.CreateRequestClient<GetCurrencyByNameRequest>();
        await Task.Delay(20000);
        var req = new GetCurrencyByNameRequest
        {
            Name = "Dollar"
        };
        //error occurs in this line
        var response = await client.GetResponse<GetCurrencyByNameResponse>(req);

        (await TestHarness.Sent.Any<GetCurrencyByNameRequest>()).Should().BeTrue();
        (await TestHarness.Consumed.Any<GetCurrencyByNameResponse>()).Should().BeTrue();

        var consumerHarness = GetConsumerTestHarness<GetCurrencyByNameConsumer>();

        (await consumerHarness.Consumed.Any<GetCurrencyByNameRequest>()).Should().BeTrue();
        var command = new CreatePackageCommand
        {
            IsActive = true,
            Description = new Translation
            {
                Arabic = StringHelper.RandomString(10),
                English = StringHelper.RandomString(10),
                Persian = StringHelper.RandomString(10),
            },
            Sort = 1,
            Name = new Translation
            {
                Arabic = StringHelper.RandomString(10),
                English = StringHelper.RandomString(10),
                Persian = StringHelper.RandomString(10),
            },
            Price = 999,
            CurrencyName = "Dollar"
        };
        var packageId = await SendAsync(command);

    }
英文:

I have two micro services with rabbitmq and masstransit v8 latest version that I send request from micro A to micro B and get data from database then response the result.
In application every thing work great but in integration test with inmemorytestharness I get this error MassTransit.RequestFaultException : The EventBus.Messages.Contracts.Services.Discounts.Currencies.Query.GetCurrencyByName.GetCurrencyByNameRequest request faulted: Cannot access a disposed object.

Message for request:

public class GetCurrencyByNameRequest
{
    public string Name { get; set; }
}

Message for response:

public class GetCurrencyByNameResponse
{
    public string Id { get; set; } 
    public string Name { get; set; } 
}

Consumer:

public class GetCurrencyByNameConsumer : IConsumer&lt;GetCurrencyByNameRequest&gt;
{
    private readonly IUnitOfWork _uow;

    public GetCurrencyByNameConsumer(IUnitOfWork uow)
    {
        _uow = uow;
    }
    public async Task Consume(ConsumeContext&lt;GetCurrencyByNameRequest&gt; context)
    {
        var filter = Builders&lt;Currency&gt;.Filter.Eq(x =&gt; x.CurrencyName, new CurrencyName(context.Message.Name));
        var currency = await _uow.GenericRepository&lt;Currency&gt;()
            .GetSingleDocumentByFilterAsync(filter, context.CancellationToken);
        if (currency == null)
        {
            await context.RespondAsync(new GetCurrencyByNameResponse
            {
                Id = string.Empty,
                Name = string.Empty
            });
        }
        else
        {
            await context.RespondAsync(new GetCurrencyByNameResponse
            {
                Id = currency.Id,
                Name = currency.CurrencyName
            });
        }
    }
}

Masstransit configuration in micro A:

   services.AddMassTransit(x =&gt;
        {
            var entryAssembly = AppDomain.CurrentDomain.GetAssemblies()
                .FirstOrDefault(x =&gt; x.FullName.Contains(&quot;Payment.Application&quot;));
            x.SetKebabCaseEndpointNameFormatter();
            x.AddConsumers(entryAssembly);
            x.UsingRabbitMq((context, cfg) =&gt;
            {
                //cfg.Host(new Uri(configuration[&quot;RabbitMqSettings:Uri&quot;]));
                cfg.Host(configuration[&quot;RabbitMqSettings:Host&quot;], configuration[&quot;RabbitMqSettings:VirtualHost&quot;], h =&gt;
                {
                    h.Username(configuration[&quot;RabbitMqSettings:Username&quot;]);
                    h.Password(configuration[&quot;RabbitMqSettings:Password&quot;]);
                });
                cfg.UseDelayedRedelivery(r =&gt; r.Intervals(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(30)));
                cfg.UseMessageRetry(r =&gt; r.Immediate(5));
                cfg.UseInMemoryOutbox();
                cfg.ConfigureEndpoints(context);
            });
        });

Masstransit configuration in micro B

  services.AddMassTransit(x =&gt;
        {
            var entryAssembly = AppDomain.CurrentDomain.GetAssemblies()
                .FirstOrDefault(x =&gt; x.FullName.Contains(&quot;Discount.Application&quot;));
            x.SetKebabCaseEndpointNameFormatter();
            x.AddConsumers(entryAssembly);
            x.UsingRabbitMq((context, cfg) =&gt;
            {
               // cfg.Host(new Uri(configuration[&quot;RabbitMqSettings:Uri&quot;]));
                cfg.Host(configuration[&quot;RabbitMqSettings:Host&quot;], configuration[&quot;RabbitMqSettings:VirtualHost&quot;], h =&gt;
                {
                    h.Username(configuration[&quot;RabbitMqSettings:Username&quot;]);
                    h.Password(configuration[&quot;RabbitMqSettings:Password&quot;]);
                });
                cfg.UseDelayedRedelivery(r =&gt; r.Intervals(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(30)));
                cfg.UseMessageRetry(r =&gt; r.Immediate(5));
                cfg.UseInMemoryOutbox();
                cfg.ConfigureEndpoints(context);
            });
        });

Masstransit inmemorytestharness configuration

 public static InMemoryTestHarness TestHarness { get; set; } = default!;
    public static IBus TestHarnessBus { get; set; } = default!;
    public static async Task UseHarnessAsync()
    {
        await using var provider = new ServiceCollection()
                .AddScoped&lt;IUnitOfWork, UnitOfWork&gt;()
              

                .AddMassTransitInMemoryTestHarness(x =&gt;
                        {
                            x.SetKebabCaseEndpointNameFormatter();
                            x.AddConsumer&lt;GetCurrencyByNameConsumer&gt;();
                            //                      .Endpoint(x=&gt;x.Name = &quot;get-currency-by-name-request&quot;);

                            x.AddConsumerTestHarness&lt;GetCurrencyByNameConsumer&gt;();
                           
                        })

                .AddGenericRequestClient()
                .BuildServiceProvider(true);

        TestHarness = provider.GetRequiredService&lt;InMemoryTestHarness&gt;();
        await TestHarness.Start().ConfigureAwait(false); 
        TestHarnessBus = provider.GetRequiredService&lt;IBus&gt;();

    }

IntegrationTest

    [Test]
    public async Task CreatePackageCommand_InsertToDb_ReturnPackage()
    {
        IRequestClient&lt;GetCurrencyByNameRequest&gt;? client = TestHarnessBus.CreateRequestClient&lt;GetCurrencyByNameRequest&gt;();
        await Task.Delay(20000);
        var req = new GetCurrencyByNameRequest
        {
            Name = &quot;Dollar&quot;
        };
        //error occurs in this line
        var response = await client.GetResponse&lt;GetCurrencyByNameResponse&gt;(req);

        (await TestHarness.Sent.Any&lt;GetCurrencyByNameRequest&gt;()).Should().BeTrue();
        (await TestHarness.Consumed.Any&lt;GetCurrencyByNameResponse&gt;()).Should().BeTrue();

        var consumerHarness = GetConsumerTestHarness&lt;GetCurrencyByNameConsumer&gt;();

        (await consumerHarness.Consumed.Any&lt;GetCurrencyByNameRequest&gt;()).Should().BeTrue();
        var command = new CreatePackageCommand
        {
            IsActive = true,
            Description = new Translation
            {
                Arabic = StringHelper.RandomString(10),
                English = StringHelper.RandomString(10),
                Persian = StringHelper.RandomString(10),
            },
            Sort = 1,
            Name = new Translation
            {
                Arabic = StringHelper.RandomString(10),
                English = StringHelper.RandomString(10),
                Persian = StringHelper.RandomString(10),
            },
            Price = 999,
            CurrencyName = &quot;Dollar&quot;
        };
        var packageId = await SendAsync(command);

    }

答案1

得分: 2

public static async Task UseHarnessAsync()
{
    await using var provider = new ServiceCollection()

一旦该方法退出,它将释放服务提供程序。


<details>
<summary>英文:</summary>

Well.

```lang-cs
public static async Task UseHarnessAsync()
    {
        await using var provider = new ServiceCollection()

As soon as that method exits, it's going to dispose of the service provider.

huangapple
  • 本文由 发表于 2023年7月28日 05:37:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76783539.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定