为什么我的单元测试对 switch 语句失败?

Why is my unit test failing for a switch statement?

您好,我正在尝试对以下内容进行单元测试并检查此 switch/case 语句是否有效:

DiagnosticsComponentFactory class

private readonly IServiceProvider _serviceCollection;

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

我的BoardItemComponentclass:

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

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

    }
}

BoardItemComponent 派生自 IComponent,在我的 Startup.cs 文件中添加如下:

services.AddScoped<IComponent, BoardItemComponent>();

我的单元测试:

[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);
}

当我调试我的单元测试时,componentnull,尽管它遵循了所有正确的步骤。它正确地进入 switch case 语句并识别出这是正确的情况,但它仍然是 returns null

根据我分享的内容(抱歉,我知道这些代码片段中的名称在没有上下文的情况下是模糊的),我的单元测试失败有什么明显的原因吗?我是 C# 单元测试的新手。

根据您的评论,您指出该组件已注册为

services.AddScoped<IComponent, BoardItemComponent>();

提供商知道 IComponent 接口,但要求 BoardItemComponent 实现

_serviceCollection.GetService<BoardItemComponent>();

如果提供者在明确请求时不知道如何解析 BoardItemComponent,则以上内容将 return null

注册实现

services.AddScoped<BoardItemComponent>();

您还可以使用工厂委托将其与抽象相关联

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

现在应该可以相应地进行隔离测试

[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);
}

现在表示以后可能会有更多的实现。

举个例子

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

然后可以重构工厂

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();
        }
    }
}