Closed nikoszs closed 5 years ago
One way to do this is to still call Startup
in your unit test to have the container configured "correctly", then explicitly register the mock object around here: https://github.com/jbogard/ContosoUniversityDotNetCore-Pages/blob/master/ContosoUniversity.IntegrationTests/SliceFixture.cs#L33
Unfortunately, the built-in container does not allow replacing instances after the service provider is built, which is what we do with other containers - create a scope, but replace the "default" instance inside the scope with the fake. This saves us from having to configure the container every single time.
Thanks so much! This helped me to get to the solution.
For anyone struggling, I just explicitly instantiated/mocked the Resolver object and added it to the services before the service provider is built (like jbogard mentioned above).
var services = new ServiceCollection();
// create mock service
var mockSomeService = new Mock<ISomeService>();
// setup mock object here
mockSomeService.Setup(x => x.DoSomething()).Returns("Something");
// create resolver with mock service
var someResolver = new SomeResolver(mockSomeService.Object);
// add resolver to service collection
services.AddSingleton<SomeResolver>(someResolver);
// add your mock service to service collection
services.AddSingleton<ISomeService>(mockSomeService);
// call your mock startup configure
// I had to create a TestingStartup class because of other dependencies,
// so this startup is basically just a lean version of the main one.
// var startup = new TestingStartup(configuration);
startup.ConfigureServices(services);
// build it
var provider = services.BuildServiceProvider();
// get your service from service provider (or just use the one already created above)
var someServiceInstance = provider.GetService<ISomeService>();
var value = someServiceInstance.DoSomething(); //gets back "Something"
// config your mapper
var config = new MapperConfiguration(cfg => {
cfg.ConstructServicesUsing(provider.GetService);
cfg.AddProfile(new MappingProfile());
cfg.AddProfile(new SomeOtherMappingProfile());
});
var mapper = config.CreateMapper();
// inject it into your controller
var controller = new SomeController(mapper, someServiceInstance);
// Act
var result = await controller.List(1);
// Assert...
For simplicity sake, I placed it all together, but definitely follow what jbogard is saying, use fixtures (and mock the service there) so you dont have to configure everything every time.
I hope this helps some one.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Hi, I'm busy setting up unit tests for my controllers. I'm mocking all services and everything works fine when automapper profiles don't use resolvers.
So inside
UserMappingProfile
I haveCreateMap<NoteDto, NoteViewModel>()
. No issues and test run fine.As soon as I start using a resolver that uses a service, my tests starts bombing.
Then update my UserMappingProfile to actually use the resolver now.
The resolver works 💯 when when the project runs normally from Startup.cs using .net core IoC container, but in my unit testing project it fails when the resolver is used.
So I dont have a DI container that adds
services.AddScoped<ICryptographyService>()
in my unit testing project, which is why it works in the main project and not my unit testing project. It makes sense why its not working, but how do I make it inject that service into the resolver?I've tried using ConstructServicesUsing with mock IServiceProvider, but it keeps telling me there's a mapping error when it hits the resolver.
My question
How can I instantiate a resolver with a mock service (ICryptoService) when setting up automapper in a unit testing project. I don't really want to mock my Startup and ConfigureServices, because then I'll have do a lot more work to mock other things. Am I missing something here?
Version
Automapper V8.1 I've also installed Automapper.DependencyInjection package.
Thanks for your time.