C# 使用XUnit Mediatr和IServiceCollection的依赖项注入
目前,我能够通过以下方式处理IServiceCollection,为特定服务注入mockC# 使用XUnit Mediatr和IServiceCollection的依赖项注入,c#,dependency-injection,xunit,mediatr,servicecollection,C#,Dependency Injection,Xunit,Mediatr,Servicecollection,目前,我能够通过以下方式处理IServiceCollection,为特定服务注入mock public class TestClass { private IMediator _mediatr; private void SetupProvider(IUnitOfWork unitOfWork, ILogger logger) { configuration = new ConfigurationBuilder().Build(); _s
public class TestClass
{
private IMediator _mediatr;
private void SetupProvider(IUnitOfWork unitOfWork, ILogger logger)
{
configuration = new ConfigurationBuilder().Build();
_services = new ServiceCollection();
_services.AddSingleton(configuration);
_services.AddScoped(x => unitOfWork);
_services.AddSingleton(logger);
_services.AddMediatR(Assembly.Load("Application"));
_services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggerBehaviour<,>));
_mediator = _services.BuildServiceProvider().GetService<IMediator>();
}
[Fact]
public async void UnitTest_Success()
{
var unitOfWork = new Mock<IUnitOfWork>();
var logger = new Mock<ILogger>();
SetupProvider(unitOfWork.Object, logger.Object);
var fixture = new Fixture();
var command = fixture.Create<MediatorCommand>();
unitOfWork.Setup(x => x.Repository.FindAll(It.IsAny<IList<long>>(), It.IsAny<bool?>()))
.ReturnsAsync(new List<Domain.Model>());
var response = await _mediatr.Send(command);
using (new AssertionScope())
{
response.Should().NotBeNull();
response.IsSuccess.Should().BeTrue();
}
}
}
公共类TestClass
{
私人媒体;
专用void设置提供程序(IUnitOfWork、ILogger记录器)
{
配置=新建ConfigurationBuilder().Build();
_服务=新服务集合();
_services.AddSingleton(配置);
_AddScoped(x=>unitOfWork);
_服务。AddSingleton(记录器);
_services.AddMediatR(Assembly.Load(“应用”));
_addScope(typeof(IPipelineBehavior),typeof(loggerbehavior));
_中介=_services.BuildServiceProvider().GetService();
}
[事实]
公共异步void UnitTest_Success()
{
var unitOfWork=new Mock();
var logger=newmock();
SetupProvider(unitOfWork.Object、logger.Object);
var fixture=新fixture();
var命令=fixture.Create();
unitOfWork.Setup(x=>x.Repository.FindAll(It.IsAny(),It.IsAny())
.ReturnsAsync(新列表());
var response=wait_mediatr.Send(命令);
使用(新断言范围())
{
response.Should().NotBeNull();
response.issucess.Should().BeTrue();
}
}
}
对于以下受试对象:
public class MediatorCommand : IRequest<CommandResponse>
{
public string Name { get; set ;}
public string Address { get; set; }
}
public class MediatorCommandHandler : IRequestHandler<MediatorCommand, CommandResponse>
{
private readonly ILogger _logger;
private readonly IUnitOfWork _unitOfWork;
public MediatorCommandHandler(IUnitOfWork unitOfWork, ILogger logger)
{
_logger = logger;
_unitOfWork = unitOfWork;
}
public async Task<CommandResponse> Handle(MediatorCommand command, CancellationToken cancellationToken)
{
var result = new CommandResponse { IsSuccess = false };
try
{
var entity = GetEntityFromCommand(command);
await _unitOfWork.Save(entity);
result.IsSuccess = true;
}
catch(Exception ex)
{
_logger.LogError(ex, ex.Message);
}
return result;
}
}
公共类中介命令:IRequest
{
公共字符串名称{get;set;}
公共字符串地址{get;set;}
}
公共类MediatorCommandHandler:IRequestHandler
{
专用只读ILogger\u记录器;
私人只读i工作单元(unitof工作单元);;
公共中介CommandHandler(IUnitOfWork、ILogger记录器)
{
_记录器=记录器;
_unitOfWork=unitOfWork;
}
公共异步任务句柄(MediatorCommand命令、CancellationToken CancellationToken)
{
var result=newcommandresponse{issucess=false};
尝试
{
var entity=GetEntityFromCommand(命令);
等待_unitOfWork.Save(实体);
result.issucess=true;
}
捕获(例外情况除外)
{
_logger.LogError(例如,例如消息);
}
返回结果;
}
}
此测试运行良好,命令处理程序中使用unitOfWork和logger模拟
我尝试移动它,以便IServiceCollection构造在每个类中进行,而不是在每个测试中使用以下内容:
public class SetupFixture : IDisposable
{
public IServiceCollection _services;
public IMediator Mediator { get; private set; }
public Mock<IUnitOfWork> UnitOfWork { get; private set; }
public SetupFixtureBase()
{
UnitOfWork = new Mock<IUnitOfWork>();
configuration = new ConfigurationBuilder().Build();
_services = new ServiceCollection();
_services.AddSingleton(configuration);
_services.AddScoped(x => UnitOfWork);
_services.AddSingleton(new Mock<ILogger>().Object);
_services.AddMediatR(Assembly.Load("Application"));
_services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggerBehaviour<,>));
Mediator = _services.BuildServiceProvider().GetService<IMediator>();
}
public void Dispose()
{
Mediator = null;
_services.Clear();
_services = null;
}
}
public class TestClass : IClassFixture<SetupFixture>
{
protected readonly SetupFixture _setupFixture;
public UnitTestBase(SetupFixture setupFixture)
{
_setupFixture = setupFixture;
}
[Fact]
public async void UnitTest_Success()
{
var fixture = new Fixture();
var command = fixture.Create<MediatorCommand>();
_setupFixture.UnitOfWork.Setup(x => x.Repository.FindAll(It.IsAny<IList<long>>(), It.IsAny<bool?>()))
.ReturnsAsync(new List<Domain.Model>());
var response = await _mediatr.Send(command);
using (new AssertionScope())
{
response.Should().NotBeNull();
response.IsSuccess.Should().BeTrue();
}
}
}
公共类SetupFixture:IDisposable
{
公共信息收集服务;
公共IMediator中介{get;private set;}
公共模拟工作单元{get;private set;}
公共SetupFixtureBase()
{
UnitOfWork=new Mock();
配置=新建ConfigurationBuilder().Build();
_服务=新服务集合();
_services.AddSingleton(配置);
_AddScoped(x=>UnitOfWork);
_services.AddSingleton(新的Mock().Object);
_services.AddMediatR(Assembly.Load(“应用”));
_addScope(typeof(IPipelineBehavior),typeof(loggerbehavior));
中介=_services.BuildServiceProvider().GetService();
}
公共空间处置()
{
调解人=null;
_服务。清除();
_服务=空;
}
}
公共类TestClass:IClassFixture
{
受保护的只读SetupFixture\u SetupFixture;
公共单元测试库(SetupFixture SetupFixture)
{
_setupFixture=setupFixture;
}
[事实]
公共异步void UnitTest_Success()
{
var fixture=新fixture();
var命令=fixture.Create();
_setupFixture.UnitOfWork.Setup(x=>x.Repository.FindAll(It.IsAny(),It.IsAny())
.ReturnsAsync(新列表());
var response=wait_mediatr.Send(命令);
使用(新断言范围())
{
response.Should().NotBeNull();
response.issucess.Should().BeTrue();
}
}
}
不幸的是,使用这种方法,我的mock不会被注入到命令处理程序中。有没有办法让它发挥作用
谢谢,我发现了这个问题,它与转到IClassFixuture无关。问题是我在初始化基类上的中介,然后在派生类上添加模拟UnitOfWork 这会导致中介初始化失败,因为其中一个Beheviour期望的UnitOfWork当时还不在容器上 在添加了所有服务之后移动中介的初始化帮助我解决了这个问题,现在所有的工作都如预期的那样 如果您尝试相同的方法,请确保在初始化任何需要这些依赖关系的对象之前,将所有服务都包含在容器中
谢谢所有有意见的人。你说的每节课是什么意思?你能再详细说明一下吗?我已经用我想用的代码修改了这个问题。我想在测试类的实例化上构建一次_服务,而不是每次运行测试。假定代码是简化的,但不完整,因此不清楚。显示已使用但未分配的变量。例如,在这两个测试示例中,
\u mediatr
在哪里分配了值。我是否能够按原样处理这段代码并重现问题?我已经更新了代码,以显示Mediator是如何实例化的