Integration tests for ASP.NET Core APIs — WebApplicationFactory, xUnit, ConfigureTestServices, FluentAssertions, database isolation
97
96%
Does it follow best practices?
Impact
99%
1.45xAverage score across 5 eval scenarios
Passed
No known issues
A small logistics company uses an internal ASP.NET Core API to track warehouse inventory. The API has been running for six months with no tests. A recent incident where a deployment broke the /api/items endpoint went undetected for two hours caused a significant disruption. The engineering manager has mandated that a minimum set of integration tests be added immediately to catch regressions before deployment.
The test infrastructure has already been scaffolded for you — a CustomWebApplicationFactory exists and is connected to the API project. Your task is to populate the test class with tests that cover the realistic failure modes the team has identified: missing data, bad inputs, resources that don't exist, and ensuring that after a write operation the data is actually retrievable. The error handling team has also requested verification that all error responses from the API share the same JSON envelope structure so clients can handle errors generically.
Produce the test class file(s) with the full set of meaningful integration tests for the API endpoints below.
Produce the following files:
tests/InventoryApi.Tests/InventoryTests.cs — the test class with all integration teststests/InventoryApi.Tests/CustomWebApplicationFactory.cs — the factory (may reuse or extend the stub below)The tests do not need to actually compile and run — the grader will inspect the source code of the test files.
The following files are provided as inputs. Extract them before beginning.
=============== FILE: inputs/src/InventoryApi/Program.cs =============== using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<InventoryDb>(opt => opt.UseInMemoryDatabase("Inventory"));
var app = builder.Build();
app.MapGet("/api/items", async (InventoryDb db) => Results.Ok(new { data = await db.Items.ToListAsync() }));
app.MapGet("/api/items/{id:int}", async (int id, InventoryDb db) => { var item = await db.Items.FindAsync(id); return item is null ? Results.NotFound(new { error = new { message = "Item not found" } }) : Results.Ok(new { data = item }); });
app.MapPost("/api/items", async (ItemRequest req, InventoryDb db) => { if (string.IsNullOrWhiteSpace(req.Sku)) return Results.BadRequest(new { error = new { message = "SKU is required" } });
var item = new InventoryItem { Sku = req.Sku, Quantity = req.Quantity };
db.Items.Add(item);
await db.SaveChangesAsync();
return Results.Created($"/api/items/{item.Id}", new { data = item });});
app.Run();
=============== FILE: inputs/src/InventoryApi/Models.cs =============== public class InventoryItem { public int Id { get; set; } public string Sku { get; set; } = ""; public int Quantity { get; set; } }
public record ItemRequest(string Sku, int Quantity);
=============== FILE: inputs/src/InventoryApi/InventoryDb.cs =============== using Microsoft.EntityFrameworkCore;
public class InventoryDb : DbContext { public InventoryDb(DbContextOptions<InventoryDb> options) : base(options) { } public DbSet<InventoryItem> Items => Set<InventoryItem>(); }
=============== FILE: inputs/tests/InventoryApi.Tests/CustomWebApplicationFactory.cs =============== using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection;
public class CustomWebApplicationFactory : WebApplicationFactory<Program> { protected override void ConfigureWebHost(Microsoft.AspNetCore.Hosting.IWebHostBuilder builder) { // TODO: configure test services here builder.UseEnvironment("Testing"); } }