简体   繁体   中英

Why is my unit test failing for a switch statement?

Hi I am trying to unit test the following and check that this switch/case statement works:

DiagnosticsComponentFactory class

private readonly IServiceProvider _serviceCollection;

public IComponent Create (string name)
{
    switch (name)
    {
        case BoardItemComponent.TypeName:
            return _serviceCollection.GetService<BoardItemComponent>();
        default:
            throw new NotSupportedException();
    }
}

My BoardItemComponent class:

public class BoardItemComponent
{
    public const string TypeName = "name";

    public BoardItemComponent(IConfigurationRepository configurationRepository) : base(configurationRepository)
    {

    }
}

BoardItemComponent is derived from IComponent , and it's added like follows in my Startup.cs file:

services.AddScoped<IComponent, BoardItemComponent>();

my unit test:

[Test]
public void GetComponent_GivenComponentFactory_ExpectBoardComponent()
{
    var serviceCollection = new ServiceCollection();
    ComponentFactoryRegistration.Register(serviceCollection);
    var factory = new DiagnosticsComponentFactory(serviceCollection.BuildServiceProvider());
    var component = factory.Create("name");
    Assert.IsNotNull(component);
}

When I debug my unit test, component is null , despite it following all the correct steps. It goes into the switch case statement correctly and recognizes that is the correct case, however it still returns null .

From what I have shared (and apologies, as I know that the names in these code snippets are vague without context), is there any obvious reason that my unit test fails? I'm new when it comes to unit testing in C#.

Based on your comments you indicated that the component is registered as

services.AddScoped<IComponent, BoardItemComponent>();

The provider is aware of the IComponent interface, but is asking for BoardItemComponent implementation

_serviceCollection.GetService<BoardItemComponent>();

The above will return null if the provider is unaware how to resolve BoardItemComponent when explicitly requested.

Register the implementation

services.AddScoped<BoardItemComponent>();

and you can also associate it with the abstraction using the factory delegate

services.AddScoped<IComponent>(sp => sp.GetRequiredService<BoardItemComponent>());

Isolated testing should now be able to be done accordingly

[Test]
public void GetComponent_GivenComponentFactory_ExpectBoardComponent() {
    //Arrange
    var serviceCollection = new ServiceCollection();
    serviceCollection.AddScoped<BoardItemComponent>();
    serviceCollection.AddScoped<IConfigurationRepository>(sp => Mock.Of<IConfigurationRepository>());

    var factory = new DiagnosticsComponentFactory(serviceCollection.BuildServiceProvider());

    //Act
    var component = factory.Create(BoardItemComponent.TypeName);

    //Assert
    Assert.IsNotNull(component);
}

Now it was indicated that there may be more implementation in the future.

Lets say for example

services.AddScoped<BoardItemComponent>();
services.AddScoped<AnotherItemComponent>();

The factory can then be refactored

public class DiagnosticsComponentFactory {    
    private readonly IServiceProvider services;

    public DiagnosticsComponentFactory (IServiceProvider services) {
        this.services = services;
    }

    public IComponent Create (string name) {
        switch (name) {
            case BoardItemComponent.TypeName:
                return services.GetRequiredService<BoardItemComponent>();
            case AnotherItemComponent.TypeName:
                return services.GetRequiredService<AnotherItemComponent>();
            default:
                throw new NotSupportedException();
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM