- Home
- .NET tutorials
- Use ASP.NET Core's TestServer in xUnit to test Web API endpoints: TestServer - Part 1
Use ASP.NET Core's TestServer in xUnit to test Web API endpoints: TestServer - Part 1
Published: Friday 20 November 2020
Using ASP.NET Core's TestServer allows us to create an in-memory web server. This allows us to write xUnit tests, focusing on endpoints in a ASP.NET Core Web API application.
How to Install TestServer in xUnit
Setting up TestServer in our xUnit test project is relatively simple.
Create an xUnit project in Visual Studio 2019
That's the xUnit project set up.
Install-Package Microsoft.AspNetCore.TestHost
How to Setup TestServer in xUnit
Now that we have the package installed into our xUnit project, we can go ahead and set up TestServer in our xUnit project.
// UnitTest1.cs
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using System;
using Xunit;
public class UnitTest1 : IDisposable
{
protected TestServer _testServer;
public UnitTest1()
{
var webBuilder = new WebHostBuilder();
webBuilder.UseStartup<Startup>();
_testServer = new TestServer(webBuilder);
}
[Fact]
public void Test1()
{
}
public void Dispose()
{
_testServer.Dispose();
}
}
// Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using RoundTheCode.CrudApi.Data;
namespace RoundTheCode.CrudApi.Tests
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddApplicationPart(Assembly.Load("RoundTheCode.CrudApi.Web")).AddControllersAsServices();
services.AddDbContext<CrudApiDbContext>();
services.AddScoped<ILeagueService, LeagueService>();
services.AddScoped<ITeamService, TeamService>();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
The Startup class needs to have the Web API methods included for it to run.
What Happens with Entity Framework in TestServer?
As is shown in our Startup class, we are setting up a reference to an Entity Framework DbContext.
public class Startup
{
public Startup(IConfiguration configuration)
{
...
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDbContext<CrudApiDbContext>();
}
...
}
Now we have two options on how we use Entity Framework in xUnit.
Using a Test Database in SQL Server
We can go ahead and create a test database in SQL Server to use in our tests.
What About Entity Framework's In-Memory Database?
The other alternative is to use Entity Framework's In-Memory database.
Install-Package Microsoft.EntityFrameworkCore.InMemory
Once that's done, we need to make a tweak when adding the DbContext into our IServiceCollection instance in the Startup class.
// Startup.cs
...
using Microsoft.EntityFrameworkCore;
using System;
namespace RoundTheCode.CrudApi.Tests
{
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDbContext<CrudApiDbContext>(options =>
{
options.UseInMemoryDatabase("MyDatabase-" + Guid.NewGuid());
});
}
...
}
}
In addition, inside our DbContext, we need to ensure that we are passing these options in as a constructor. When doing this, we can call the base constructor that will do all the work in configuring the options for our DbContext.
// CrudApiDbContext.cs
namespace RoundTheCode.CrudApi.Data
{
public class CrudApiDbContext : DbContext
{
...
public CrudApiDbContext(DbContextOptions<CrudApiDbContext> options) : base(options)
{
}
...
}
}
How to Run an Endpoint in TestServer
With the DbContext setup, we can go ahead and actually test our endpoints.
...
using System.Net;
using System.Threading.Tasks;
namespace RoundTheCode.CrudApi.Tests
{
public class UnitTest1 : IDisposable
{
...
[Fact]
public async Task TestReadMethods()
{
var response = await _testServer.CreateRequest("/api/league/1").SendAsync("GET");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
response = await _testServer.CreateRequest("/api/league/2").SendAsync("GET");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
...
}
}
Running those tests should give us a green tick.
What about Handling Post Requests and Limiting Instances of TestServer?
Coming up, we will have a look at some useful TestServer tips, such as firing a post request and limiting the number of instances of TestServer.
Related tutorials