使用Nsubstitute为IOC容器注册或配置
本文关键字:注册 配置 Nsubstitute IOC 使用 | 更新日期: 2024-10-24 01:37:57
我有一个自定义的IOC容器,它接受Interface和Concrete类型作为要注册的参数。在我的项目中,我已经注册了下面代码中提到的配置。你能帮助我某人如何使用NSubstitute在单元测试项目中注册吗?
IOC-Conatincer.cs
Register<Intf, Impl>();
应用程序-配置.cs
Register<ICustomer,Customer>();
单元测试应用程序-CustomerTest.cs
Register<ICustomer,StubCustomer>(); -I want something like this
var substitute = Substitute.For<ICustomer>(); but It provides something like this
我不认为你可以让Unity解析具体的实例,然后在上面提供N替代属性/方法。
由于您的意图是进行单元测试,因此需要使用NSubstitue解析的实例,因为只有使用该实例,您才能配置属性/方法以返回对象或检查是否收到调用。
没有像Concrete类那样直接使用的方法,作为一种变通方法,为Register()添加了一个OverLoaded方法,并将其作为参数传递
Container.cs
public class IOCContainer
{
static Dictionary<Type, Func<object>> registrations = new Dictionary<Type, Func<object>>();
public static void Register<TService, TImpl>() where TImpl : TService
{
registrations.Add(typeof(TService), () => Resolve(typeof(TImpl)));
}
public static void Register<TService>(TService instance)
{
registrations.Add(typeof(TService), () => instance);
}
public static TService Resolve<TService>()
{
return (TService)Resolve(typeof(TService));
}
private static object Resolve(Type serviceType)
{
Func<object> creator;
if (registrations.TryGetValue(serviceType, out creator)) return creator();
if (!serviceType.IsAbstract) return CreateInstance(serviceType);
else throw new InvalidOperationException("No registration for " + serviceType);
}
private static object CreateInstance(Type implementationType)
{
var ctor = implementationType.GetConstructors().Single();
var parameterTypes = ctor.GetParameters().Select(p => p.ParameterType).ToList();
var dependencies = parameterTypes.Select(Resolve).ToArray();
return Activator.CreateInstance(implementationType, dependencies);
}
}
配置.cs
IOCContainer.Register(Substitute.For<IProvider>());
IOCContainer.Register(Substitute.For<ICustomer>());
我建议您使用一种工具来实现自动模拟容器模式,这是一种可以用来解决问题的单元测试模式:"如何将单元测试与依赖注入机制解耦?"
有关此模式的更多详细信息,请参阅本文:https://blog.ploeh.dk/2013/03/11/auto-mocking-container/
我建议您使用的具体工具是AutoFixture,它更多的是在中创建用于测试的假对象,但它也提供自动模拟容器功能。
以下是我如何在我的项目中使用NSubstitute:
所需库:NSubstitute、AutoFixture和AutoFixture.AutoNSubstitute
[TestClass]
public class BuildingServiceTest
{
private IFixture fixture;
private IBuildingRepository repository;
private BuildingService sut;
private IBuildingServiceValidator validator;
[TestInitialize]
public void TestInitialize()
{
fixture = new Fixture().Customize(new AutoNSubstituteCustomization());
repository = fixture.Freeze<IBuildingRepository>();
validator = fixture.Freeze<IBuildingServiceValidator>();
sut = fixture.Create<BuildingService>();
}
[TestMethod]
public async Task CreateAsync_WithInvalidBuildings_ReturnsBadRequest()
{
// Arrange
var buildingForCreationDto = fixture.Create<BuildingForCreationDto>();
var validationResultWithErrors = CreateValidationResultWithErrors();
validator.Validate(Arg.Any<CreateBuildingCommand>()).Returns(validationResultWithErrors);
// Act
var actual = await sut.CreateAsync(buildingForCreationDto);
// Assert
actual.StatusCode.Should().Be(HttpStatusCode.BadRequest);
actual.Errors.Should().BeEquivalentTo(FailureDto.FromValidationFailures(validationResultWithErrors.Errors));
}
}