在测试中使用 MediatR 时无法访问已处置的对象 (IServiceProvider)
Cannot access a disposed object (IServiceProvider) while using MediatR in tests
我收到以下错误:
Cannot access a disposed object.
Object name: 'IServiceProvider'.
尝试调用 _mediator.Send
方法时。
只有当我尝试测试控制器的方法时才会发生这种情况。每当从 api 调用控制器时,它似乎工作正常。
控制器:
public class Controller : ControllerBase
{
private readonly IMediator mediator;
public Controller(IMediator mediator)
{
this.mediator = mediator;
}
[HttpPost]
public async Task<IActionResult> Post(Command command)
{
try
{
await mediator.Send(command); // exception occurs here
return Ok();
}
catch (Exception ex)
{
return BadRequest(ex.InnerException?.Message ?? ex.Message);
}
}
}
请求处理程序:
public class CommandHandler
: IRequestHandler<Command, bool>
{
private readonly AppDbContext dbContext;
public CommandHandler(AppDbContext dbContext)
{
this.dbContext = dbContext;
}
public async Task<bool> Handle(Command request, CancellationToken cancellationToken)
{
try
{
await dbContext.Companies.AddAsync(new Company(request.CompanyId, request.CompanyName), cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
return true;
}
catch(Exception)
{
throw;
}
}
}
MediatR 是这样注册的:
services.AddMediatR(Assembly.GetExecutingAssembly());
我正在尝试使用真实数据库连接测试此控制器。
protected Controller GetController() // method where controller is created and mediatR injected
{
using var scope = _scopeFactory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
return new Controller(mediator);
}
protected async Task<IActionResult> PostControllerMethod(Command command) // this method is call in test method
=> await GetController().Post(command);
解决问题的唯一方法是将MediatR注册为单例:
services.AddMediatR(mediatRServiceConfiguration => mediatRServiceConfiguration.AsSingleton(), Assembly.GetExecutingAssembly());
我不确定后果。
在“using”结束时,作用域被释放。
当您将此 'mediator' 返回给 Controller 时,范围已被释放并且 'mediator' 无法访问。
尝试在你想使用的地方解析 'mediator'
protected Controller GetController() // method where controller is created and mediatR injected
{
using var scope = _scopeFactory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
return new Controller(mediator);
}
我收到以下错误:
Cannot access a disposed object.
Object name: 'IServiceProvider'.
尝试调用 _mediator.Send
方法时。
只有当我尝试测试控制器的方法时才会发生这种情况。每当从 api 调用控制器时,它似乎工作正常。
控制器:
public class Controller : ControllerBase
{
private readonly IMediator mediator;
public Controller(IMediator mediator)
{
this.mediator = mediator;
}
[HttpPost]
public async Task<IActionResult> Post(Command command)
{
try
{
await mediator.Send(command); // exception occurs here
return Ok();
}
catch (Exception ex)
{
return BadRequest(ex.InnerException?.Message ?? ex.Message);
}
}
}
请求处理程序:
public class CommandHandler
: IRequestHandler<Command, bool>
{
private readonly AppDbContext dbContext;
public CommandHandler(AppDbContext dbContext)
{
this.dbContext = dbContext;
}
public async Task<bool> Handle(Command request, CancellationToken cancellationToken)
{
try
{
await dbContext.Companies.AddAsync(new Company(request.CompanyId, request.CompanyName), cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
return true;
}
catch(Exception)
{
throw;
}
}
}
MediatR 是这样注册的:
services.AddMediatR(Assembly.GetExecutingAssembly());
我正在尝试使用真实数据库连接测试此控制器。
protected Controller GetController() // method where controller is created and mediatR injected
{
using var scope = _scopeFactory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
return new Controller(mediator);
}
protected async Task<IActionResult> PostControllerMethod(Command command) // this method is call in test method
=> await GetController().Post(command);
解决问题的唯一方法是将MediatR注册为单例:
services.AddMediatR(mediatRServiceConfiguration => mediatRServiceConfiguration.AsSingleton(), Assembly.GetExecutingAssembly());
我不确定后果。
在“using”结束时,作用域被释放。 当您将此 'mediator' 返回给 Controller 时,范围已被释放并且 'mediator' 无法访问。 尝试在你想使用的地方解析 'mediator'
protected Controller GetController() // method where controller is created and mediatR injected
{
using var scope = _scopeFactory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
return new Controller(mediator);
}