I'm trying to replace an implementation of IMessageFormatter
with a MockMessageFormatter
for a test.
public class MyMockingWebApplicationFactory<TStartUp> : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services => { services.AddTransient<IMessageFormatter, MockMessageFormatter>(); });
}
}
The test looks like so:
public class MockingTests : IClassFixture<MyMockingWebApplicationFactory<Startup>>
{
public MockingTests(MyMockingWebApplicationFactory<Startup> webApplicationFactory)
{
_webApplicationFactory = webApplicationFactory;
}
private readonly MyMockingWebApplicationFactory<Startup> _webApplicationFactory;
[Fact]
public async Task MockIt()
{
var client = _webApplicationFactory.WithWebHostBuilder(builder =>
{
//builder.ConfigureServices(services =>
//{
// var foo = ServiceDescriptor.Transient<IMessageFormatter, MessageFormatter>();
// services.Remove(foo);
// services.AddTransient<IMessageFormatter, MockMessageFormatter>();
//});
}).CreateClient();
var message = "Hello";
var expectedReversedMessage = "foo";
var result = await client.GetAsync($"/?message={message}");
var content = await result.Content.ReadAsStreamAsync();
var htmlParser = new HtmlParser();
var htmlDocument = await htmlParser.ParseAsync(content);
var messageElement = htmlDocument.GetElementById("original-message");
var reversedMessageElement = htmlDocument.GetElementById("reversed-message");
Assert.Equal(message, messageElement.InnerHtml);
var reversedMessage = reversedMessageElement.InnerHtml;
Assert.Equal(expectedReversedMessage, reversedMessage);
}
}
I've tried adding the call to ConfigureServices
in the client and in the MyMockingWebApplicationFactory
but the problem seems to be that the real Startup
class is executed after the test's registration and so overwrites them.
The real StartUp
class is:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); ;
services.AddTransient<IMessageFormatter, MessageFormatter>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseMvc();
}
}
replace your code :
builder.ConfigureServices(services => { services.AddTransient<IMessageFormatter, MockMessageFormatter>(); });
to:
builder.ConfigureTestServices(services =>
{
var serviceProvider = services.BuildServiceProvider();
var descriptor =
new ServiceDescriptor(
typeof(IMessageFormatter),
typeof(MockMessageFormatter),
ServiceLifetime.Transient);
services.Replace(descriptor);
});
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