In my .NET6 project, I have some minimal APIs and I want to test them. You find the full source code on GitHub. For that, I created a new NUnit test project. In the project file, I added PreserveCompilationContext
and the file looks like
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<PreserveCompilationContext>true</PreserveCompilationContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\MinimalApis.csproj" />
</ItemGroup>
</Project>
Then, I created an implementation of WebApplicationFactory like that
class MinimalApisApplication : WebApplicationFactory<Program>
{
protected override IHost CreateHost(IHostBuilder builder)
{
var root = new InMemoryDatabaseRoot();
builder.ConfigureServices(services =>
{
services.RemoveAll(typeof(DbContextOptions<ClientContext>));
services.AddDbContext<ClientContext>(options =>
options.UseInMemoryDatabase("Testing", root));
});
return base.CreateHost(builder);
}
}
Finally, my test class is like that
public class Tests
{
[SetUp]
public void Setup()
{
}
[Test]
public async Task GetClients()
{
await using var application = new MinimalApisApplication();
var client = application.CreateClient();
var notes = await client.GetFromJsonAsync<List<ClientModel>>("/clients");
Assert.IsNotNull(notes);
Assert.IsTrue(notes.Count == 0);
}
}
When I run the project, I receive an error
System.InvalidOperationException : Can't find 'C:\Projects\Net6MinimalAPIs\MinimalApis.Tests\bin\Debug\net6.0\testhost.deps.json'. This file is required for functional tests to run properly. There should be a copy of the file on your source project bin folder. If that is not the case, make sure that the property PreserveCompilationContext is set to true on your project file. E.g 'true'. For functional tests to work they need to either run from the build output folder or the testhost.deps.json file from your application's output directory must be copied to the folder where the tests are running on. A common cause for this error is having shadow copying enabled when the tests run.
I googled a bit but I can't find how to generate this file.
Update
I tried to add a xUnit
project with the same result. Also, I noticed that Program
is coming from
using Microsoft.VisualStudio.TestPlatform.TestHost;
because I added this reference but this is wrong. I want to refer to the Program
in the main project but it is unaccessbile due to its protection level. The Program.cs
looks
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ClientContext>(opt =>
opt.UseInMemoryDatabase("Clients"));
builder.Services
.AddTransient<IClientRepository,
ClientRepository>();
builder.Services
.AddAutoMapper(Assembly.GetEntryAssembly());
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo {
Title = builder.Environment.ApplicationName, Version = "v1"
});
});
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("v1/swagger.json",
$"{builder.Environment.ApplicationName} v1");
});
app.MapFallback(() => Results.Redirect("/swagger"));
// Get a shared logger object
var loggerFactory =
app.Services.GetService<ILoggerFactory>();
var logger =
loggerFactory?.CreateLogger<Program>();
if (logger == null)
{
throw new InvalidOperationException(
"Logger not found");
}
// Get the Automapper, we can share this too
var mapper = app.Services.GetService<IMapper>();
if (mapper == null)
{
throw new InvalidOperationException(
"Mapper not found");
}