Reputation: 27
Using xUnit 2.4.1 to test the Api always fails to find Controller
When I create a WebApplicationFactory
and pass Startup file as parameter the HTTP Client from WebApplicationFactory.CreatVlient()
always returns 404 for Get requests.
Testing a .Net Core Api that uses MVC.
The CommonContext
is an internal class that sets the connection.
The Configfile
reads correctly
The Connectionstring
to DB is correct
The Endpoint is not called correctly and therefore never hits the controller.
Class that inherits WebApplocationFactory
public class WebApiTestFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup: class
{
protected override IWebHostBuilder CreateWebHostBuilder()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
var configValues = new Dictionary<string, string>
{
{"RunStatus", "Test"},
};
builder.AddInMemoryCollection(configValues);
return WebHost.CreateDefaultBuilder()
.UseConfiguration(builder.Build())
.UseUrls("http://localhost:53976/")
.UseSetting("applicationUrl", "http://localhost:53976/")
.UseStartup<Else.WebApi.Core.Startup>();
}
}
Unit Test
public class TestControllerTest : IClassFixture<WebApiTestFactory<Startup>>
{
private readonly WebApiTestFactory<Startup> _factory;
public TestControllerTest(WebApiTestFactory<Startup> factory)
{
_factory = factory;
}
[Theory]
[InlineData("api/Test/GetExample")]
public async Task Create(string url)
{
// Arrange
var clientOptions = new WebApplicationFactoryClientOptions();
clientOptions.BaseAddress = new Uri("http://localhost:53976");
var client = _factory.CreateClient(clientOptions);
// Act
var response = await client.GetAsync(url);
// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.Equal("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
}
Controller is in the project im testing
[ApiController]
[Route("api/Test")]
public class TestController : Controller
{
[HttpGet("GetExample")]
public ActionResult GetExample()
{
return Ok();
}
}
Startup
public class Startup
{
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
HostingEnvironment = env;
Configuration = configuration;
EwBootstrapper.BootstrapElsewareServices();
}
public IConfiguration Configuration { get; }
public IHostingEnvironment HostingEnvironment { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
if (Configuration["RunStatus"] != "Test")
{
services.AddTransient<AuthenticationTokens>();
services.AddTransient<IPasswordValidator, PasswordValidator>();
services.AddTransient<IUserRepository, UserRepository>();
services.AddMvc();
services.AddScoped(_ =>
new CommonContext(Configuration.GetConnectionString("DbConnection")));
services.AddSwaggerDocumentation();
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) // Configure authentication (JWT bearer)
.AddJwtBearer(jwtOpt => // Configure JWT bearer
{
jwtOpt.TokenValidationParameters = AuthenticationTokens.GetValidationParameters();
});
}
else
{
//services.AddMvcCore().AddJsonFormatters();
services.AddScoped(_ =>
new CommonContext(Configuration.GetConnectionString("DbTestConnection")));
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
if (Configuration["RunStatus"] != "Test")
{
app.UseSwaggerDocumentation();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "API");
});
app.UseMiddleware<ApiLoggerMiddleware>();
app.UseMvc(builder => builder.MapRoute("Default", "api/{controller}/{action=Get}/{id?}")); // No default values for controller or action
app.UseDefaultFiles(); // Enable default documents ( "/" => "/index.html")
app.UseStaticFiles(); // Static files under wwwroot
app.UseAuthentication();
}
if (HostingEnvironment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
}
}
Upvotes: 0
Views: 591
Reputation: 23945
According to the attribute routing in your controller, the action method has the url api/Test/GetExample
: [HttpGet("GetExample")]
, yet in your in test you are testing for CreateExample
:
[InlineData("api/Test/CreateExample")]
So I guess, your test is correct in returning a 404. That route simply will not resolve to any existing action method.
I suggest you change your theory to [InlineData("api/Test/GetExample")]
Upvotes: 1