I'm using AspNetCore 2.2 Following (moreless) the docs here: https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2
I am using Autofac, my Startup class has the following methods:
public void ConfigureServices(IServiceCollection services)
public void ConfigureContainer(ContainerBuilder containerBuilder) //this is where things can be registered directly with autofac and runs after ConfigureServices
public void Configure(...) //the method called by runtime
The way I use Autofac, as recommended by its docs, is by having Program.cs like this
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.ConfigureServices(services => services.AddAutofac())
.UseIISIntegration()
.UseStartup<Startup>()
.ConfigureAppConfiguration((builderContext, config) =>
{
var env = builderContext.HostingEnvironment;
config
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true)
.AddEnvironmentVariables();
});
}
I am now using TestServer for my test project where I want to use the real Startup class. But I would like to modify one of the dependencies.
I have seen that there is a method available on WebHostBuilder
to .ConfigureTestServices(services => {});
so I tried the following:
public abstract class ComponentTestFeature
: Feature
{
protected HttpClient HttpClient { get; }
protected ComponentTestFeature()
{
var configuration =
new ConfigurationBuilder()
.AddJsonFile("appsettings.Test.json")
.Build();
var webHostBuilder =
new WebHostBuilder()
.ConfigureServices(services => services.AddAutofac())
.ConfigureTestServices(services =>
{
services.AddScoped<IEventStoreManager, MockEventStoreManager>();
})
.UseConfiguration(configuration)
.UseStartup<Startup>();
var server = new TestServer(webHostBuilder);
HttpClient = server.CreateClient();
var myService = server.Host.Services.GetRequiredService<IEventStoreManager>();
}
}
As you can see I want to use a MockEventStoreManager
implementation for IEventStoreManager
so that this is the implementation that should be resolved by the container. However this is not working as expected and myService resolved is the original implementation, the real one, not the mock one.
Does anybody know how could I achieve what I want?
UPDATE 1: After more investigation I had to create an issue on github AspNetCore because the extension method is executed before the ConfigureContainer, therefore I cannot really override autofac dependencies nor retrieve autofac container later on. https://github.com/aspnet/AspNetCore/issues/6522
UPDATE 2: Just FYI, this is how the Startup.cs looks like. As you can see all the dependencies but mvc are registered in autofac's container.
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This is where things can be registered directly with autofac and runs after ConfigureServices, so it will override it
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<EventStoreManager>().As<IEventStoreManager>();
}
and what I want to do is to use MockEventStoreManager
implementation for IEventStoreManager
in my tests, so I need to override (from my test project) that Autofac's registration in a nice way.
IEventStoreManager
registered?ConfigureServices
or directly with the container inConfigureContainer
? – GlendaglendenConfigureContainer
, with autofac container – ThreadyConfigureTestServices
, there is aConfigureTestContainer<TContainer>
that can be used to directly manipulate the container. Check updated answer. – Glendaglenden