使用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

使用Nsubstitute为IOC容器注册或配置

我不认为你可以让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:

所需库:NSubstituteAutoFixtureAutoFixture.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));
    }
}