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.