image

Web Design & Development Article

Minimal APIs in .NET 6 but where are the Unit Tests?

Published:

Minimal APIs in .NET 6 is great. But where are the Unit Tests?! Often testing is missed or forgotten because it's perceived as difficult or complex. Exploring a minimal Web API with ASP.NET Core 6 A .NET 6 Minimal API Todo example Playground Exploring a minimal WebAPI with ASP.NET Core Easier functional and integration testing of ASP.NET Core applications Automatic Unit Testing in .NET Core plus Code Coverage in Visual Studio Code But it's super fun and very easy! Once tests are easy to write, WRITE A LOT OF THEM. Here's a simple Unit Test of a Web API:[Fact]public async Task GetTodos(){ await using var application = new TodoApplication(); var client = application.CreateClient(); var todos = await client.GetFromJsonAsync<List<Todo>>("/todos"); Assert.Empty(todos);} Look how nice that is. Client and Server (Application) are right there, and the HTTP GET is just a function call (as this is a Unit Test, not an integration test that covers end-to-end full stack). Here's the TodoApplication application factory that creates a Host with a mocked out in memory version of a SQLite database.class TodoApplication : WebApplicationFactory<Todo>{ protected override IHost CreateHost(IHostBuilder builder) { var root = new InMemoryDatabaseRoot(); builder.ConfigureServices(services => { services.AddScoped(sp => { // Replace SQLite with the in memory provider for tests return new DbContextOptionsBuilder<TodoDbContext>() .UseInMemoryDatabase("Tests", root) .UseApplicationServiceProvider(sp) .Options; }); }); return base.CreateHost(builder); }} Nice and clean. You're talking directly to the API, testing just the Unit of Work. No need for HTTP, you're just calling a clean method on the existing API, directly. That's a simple example, just getting Todos. How would we test making one (POSTing to our Todo application as a Minimal .NET 6 API?)[Fact]public async Task PostTodos(){ await using var application = new TodoApplication(); var client = application.CreateClient(); var response = await client.PostAsJsonAsync("/todos", new Todo { Title = "I want to do this thing tomorrow" }); Assert.Equal(HttpStatusCode.Created, response.StatusCode); var todos = await client.GetFromJsonAsync<List<Todo>>("/todos"); Assert.Single(todos); Assert.Equal("I want to do this thing tomorrow", todos[0].Title); Assert.False(todos[0].IsComplete);} You could abstract the setup away if you wanted to and start with an Server/App and Client ready to go, but it's just two lines. Here we are asserting that it returned an HTTP 200 - even though the HTTP networking stack isn't involved we are still able to test intent. Then we confirm that we created a Todo and could successfully retrieve it from the (in-memory) database. Pretty slick! Sponsor: YugabyteDB is a distributed SQL database designed for resilience and scale. It is 100% open source, PostgreSQL-compatible, enterprise-grade, and runs across all clouds. Sign up and get a free t-shirt.(C) 2021 Scott Hanselman. All rights reserved.     

Read This Article

A quote within 24 hours

Contact Us