概述
所以我有一个现有的web,它使用MediatR命令。我正致力于将MT集成到其中一些中,以便为各种目的向RMQ发布消息。我能够很好地将它集成到我的命令中,但是在集成测试期间,我在用InMemoryHarness进行测试时遇到了问题。
详细信息
我有一个NUnit测试夹具,它可以像医生们描述的那样设置内存管理。
[OneTimeSetUp]
public async Task RunBeforeAnyTests()
{
var dockerDbPort = await DockerDatabaseUtilities.EnsureDockerStartedAndGetPortPortAsync();
var dockerConnectionString = DockerDatabaseUtilities.GetSqlConnectionString(dockerDbPort.ToString());
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddEnvironmentVariables();
_configuration = builder.Build();
var services = new ServiceCollection();
// various other registration
// MassTransit Setup -- Do Not Delete Comment
_provider = services.AddMassTransitInMemoryTestHarness(cfg =>
{
// Consumers here
}).BuildServiceProvider(true);
_harness = _provider.GetRequiredService<InMemoryTestHarness>();
await _harness.Start();
}
我还有一个MediatR处理程序,它看起来可能如下所示:
public class Handler : IRequestHandler<AddRecipeCommand, RecipeDto>
{
private readonly RecipesDbContext _db;
private readonly IMapper _mapper;
private readonly IPublishEndpoint _publishEndpoint;
public Handler(RecipesDbContext db, IMapper mapper, IPublishEndpoint publishEndpoint)
{
_mapper = mapper;
_publishEndpoint = publishEndpoint;
_db = db;
}
public async Task<RecipeDto> Handle(AddRecipeCommand request, CancellationToken cancellationToken)
{
var recipe = _mapper.Map<Recipe> (request.RecipeToAdd);
_db.Recipes.Add(recipe);
await _publishEndpoint.Publish<IRecipeAdded>(new
{
RecipeId = recipe.Id
});
await _db.SaveChangesAsync();
return await _db.Recipes
.ProjectTo<RecipeDto>(_mapper.ConfigurationProvider)
.FirstOrDefaultAsync(r => r.Id == recipe.Id);
}
}
我有一个像这样的测试,在注射IPublishEndpoint
之前就通过了
[Test]
public async Task can_add_new_recipe_to_db()
{
// Arrange
var fakeRecipeOne = new FakeRecipeForCreationDto { }.Generate();
// Act
var command = new AddRecipe.AddRecipeCommand(fakeRecipeOne);
var recipeReturned = await SendAsync(command);
var recipeCreated = await ExecuteDbContextAsync(db => db.Recipes.SingleOrDefaultAsync());
// Assert
recipeReturned.Should().BeEquivalentTo(fakeRecipeOne, options =>
options.ExcludingMissingMembers());
recipeCreated.Should().BeEquivalentTo(fakeRecipeOne, options =>
options.ExcludingMissingMembers());
}
但是,当MediatR命令包括MT发布时,测试失败:
----> System.InvalidOperationException : Unable to resolve service for type 'MassTransit.IPublishEndpoint' while attempting to activate 'RecipeManagement.Domain.Recipes.Features.AddRecipe+Handler'.
我在哪里
同样,这个MediatR命令在针对RMQ运行实际应用程序时运行良好,但是内存管理似乎没有引入总线来正确注入IPublishEndpoint
。
我试过把这样的东西带来不同的口味,但都没有用。
var bus = _provider.GetRequiredService<IBus>();
services.AddSingleton<IPublishEndpoint>(bus);
我想我可以使用一个带有RMQ的坞容器,并将它用于我的测试,但是如果我能够使用内存中的工具来实现性能和简单性,那就太好了。
对于我该如何处理这件事,有什么想法吗?
发布于 2021-10-05 03:29:15
已更新
因此,下面的方法会起作用,但它不会让您从发布的角度测试任何针对工具的测试,这显然不是理想的,如果您像这样设置注册,它现在应该会飞起来:
services.AddMassTransitInMemoryTestHarness(cfg =>
{
// Consumer Registration -- Do Not Delete Comment
cfg.AddConsumer<AddToBook>();
cfg.AddConsumerTestHarness<AddToBook>();
});
_provider = services.BuildServiceProvider();
_scopeFactory = _provider.GetService<IServiceScopeFactory>();
_harness = _provider.GetRequiredService<InMemoryTestHarness>();
await _harness.Start();
年长的
因此,内存中的db似乎没有办法尽可能地为消费者注册IPublishEndpoint
:
_provider = services.AddMassTransitInMemoryTestHarness(cfg =>
{
cfg.AddConsumer<AddToBook>();
cfg.AddConsumerTestHarness<AddToBook>();
}).BuildServiceProvider();
_harness = _provider.GetRequiredService<InMemoryTestHarness>();
但我所能做的只是使用Moq
来添加一个模拟。我不需要在这个级别测试发布后会发生什么,因为这是一个进程外操作,所以这样做可以完成注册工作,从而使我的DI高兴。
services.AddScoped(_ => Mock.Of<IPublishEndpoint>());
https://stackoverflow.com/questions/69417049
复制相似问题