I'm having hard times to test a Factory that uses the .net core ServiceProvider
to return a particular implementation given some logic.
using (var scope = _serviceProvider.CreateScope())
{
var services = scope.ServiceProvider.GetServices<IUrlProcessor>();
}
I'm partially have this with
var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(m => m.GetService(typeof(IEnumerable<IUrlProcessor>)))
.Returns(new List<IUrlProcessor>() {
new PassthruProcessor()
});
The GetServices
seems to work but the CreateScope
call just throughs an exception. It is an extension method I don't know what is the exact class I should mock so that the CreateScope
call works.
In this scenario it probably doesn't help to create mocks that return more mocks. Your class depends on an IServiceProvider
, and you need to call CreateScope()
.
Mocking IServiceProvider
to return another mock is functionally the same as using a real ServiceProvider
and configuring it to return a mock. The difference is that if you use a real ServiceProvider
you don't also have to mock CreateScope
.
(I'm totally sidestepping questions about where and when to depend on the IServiceProvider.
)
Here's a drastically simplified example:
The class that depends on an IServiceProvider
:
public class ScopedFooFactory : IFooFactory
{
private readonly IServiceProvider _serviceProvider;
public ScopedFooFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IFoo CreateFoo()
{
using (var scope = _serviceProvider.CreateScope())
{
return scope.ServiceProvider.GetService<IFoo>();
}
}
}
...and some unit test code:
var serviceCollection = new ServiceCollection();
var fooMock = new Mock<IFoo>();
serviceCollection.AddScoped<IFoo>(provider => fooMock.Object);
var serviceProvider = serviceCollection.BuildServiceProvider();
var subject = new ScopedFooFactory(serviceProvider);
var foo = subject.CreateFoo();
Assert.AreSame(fooMock.Object, foo);
To me this is simpler and easier than creating a mock that returns more mocks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With