1

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.

enter image description here

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");
}
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
Enrico
  • 3,592
  • 6
  • 45
  • 102
  • Have you tried putting a classic `public class` + `public static Main(string[] args)` in your `Program.cs` ? AFAIK the "implicit" class is internal – Meikel Jun 22 '22 at 09:00
  • 2
    IMHO, this question should not be closed as a duplicate. The other questions are closely related, to be sure, but *not* the same issue. In the OP's use of WebApplicationFactory the type passed for the type parameter was very likely Microsoft.VisualStudio.TestPlatform.TestHost.Program rather than the Program type from their host assembly. This is why the error reports a missing testhost.deps.json rather than one for an assembly actually included in the solution. It's an easy mistake to make and miss. – Ryan Sep 27 '22 at 15:32
  • I agree with @Ryan, just look at the title, this isn't a duplicate of them. And +1, the comment should be an answer, because it worked for me, indeed I missed the `Program` reference as you mentioned. – alexDuty Aug 10 '23 at 15:24
  • did you tried this? ` ` [as per docs](https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-7.0) – alexDuty Aug 10 '23 at 15:35

0 Answers0