0

Is it possible to create multiple TestServers for an integration test in dotnet 6?

With dotnet 3.1 this was possible because I could reference Startup.cs from the integration test. With dotnet 6 the Program.cs and Startup.cs became Program.cs. Now when I try to reference the Program.cs for the WebHostBuilder.UseStartup() this is not possible because I have multiple Program.cs and the Program.cs files don't have a namespace.

In dotnet 3.1 I had

var application1 = new WebHostBuilder().UseStartup<Poject1.Startup>()
var application2 = new WebHostBuilder().UseStartup<Poject2.Startup>()
var application3 = new WebHostBuilder().UseStartup<Poject3.Startup>()

In dotnet 6 this is not possible?

var application1 = new WebApplicationFactory<TProgram>().UseStartup<Poject1.Program>()
var application2 = new WebApplicationFactory<TProgram>().UseStartup<Poject2.Program>()
var application3 = new WebApplicationFactory<TProgram>().UseStartup<Poject3.Program>()

I get the error: The Type 'Program' exists in both 'Project1...' and 'Project2...'

The Program.cs files look like this:

// usings

var builder = WebApplication.CreateBuilder(args);

// inject services

var app = builder.Build();

// configure services

app.Run();

public partial class Program { }

Does anyone have a solution?

Brian
  • 129
  • 1
  • 9
  • Post the actual code and actual *full* exception text or compilation error. The error tells you that the `Program` classes are mixed up. Somehow, somewhere it's unclear which `Program` class is used. – Panagiotis Kanavos Jul 21 '22 at 11:56
  • The problem is obvious but there is not solution for it when I search the Microsoft documentation or stackoverflow. I have 3 projects with 3 Program.cs. In .NET 3.1 the Startup.cs classes had namespaces but the new Program.cs classes don't have a namespace so I can't use 'Project1.Program' for example – Brian Jul 21 '22 at 12:04
  • The problem may be obvious to you but I can't tell if that's a compilation error or exception, or where it's raised. [Integration testing](https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0) is typically performed through the `WebApplcationFactory<>` class, not by starting a real host – Panagiotis Kanavos Jul 21 '22 at 12:42
  • Googling for `The Type 'Program' exists in both` shows this is a compilation error with hits going back to 2006. It's caused when the same type *in the same namespace* appears in multiple assemblies or assembly versions. This error was also reported in ASP.NET MVC 2 projects from 2011, because the code generation used by ASP.NET resulted in classes being created in the same (perhaps the global?) namespace. This may be the case here too. – Panagiotis Kanavos Jul 21 '22 at 12:53
  • In any case, if you want to start several services for integration testing starting multiple hosts is a *dangerous* idea. All hosts run under the same process so they aren't isolated. Static data will be common for all hosts. If you have a common library with some singletons or static classes, making a modification in one project will be visible to all others as well. In such cases it's better to containerize the projects and start them in separate containers just for testing – Panagiotis Kanavos Jul 21 '22 at 12:55
  • It may not even be your code. A lot of libraries use caching in static fields. Serializers cache type information and metadata for example. One example is XmlSerializer. – Panagiotis Kanavos Jul 21 '22 at 12:57
  • I get what you are saying. I can use WebApplcationFactory but the problem here is that I cannot reference 3 different Program.cs files because they do not have a namespace. The namespace is removed because with dotnet 6 you can write it like the example I have written in the description. So I need a namespace in my Program.cs files. But I think the only solution then is to make a Program.cs and Startup.cs file the old dotnet 3.1 way – Brian Jul 21 '22 at 13:25
  • When you use `Project1.Program` you *are* specifying a namespace, `Project1`. That's why this is weird and why you need to post the actual code *and actual full compilation error*. Where does the error appear? – Panagiotis Kanavos Jul 21 '22 at 13:31
  • Project1 is the project name. I want to use 3 different Program.cs files from 3 different projects in my integration test but the Program.cs files don't have a namespace in the new .net 6. – Brian Jul 21 '22 at 13:32
  • That's not what I asked. It's clear from the start that you want to use 3 projects. What isn't clear is the actual test code, the actual full error text and its location. Besides, top-level programs don't use `new WebHostBuilder().UseStartup()`, they use `WebApplication.CreateBuilder`. I don't know if `UseStartup` can guess that you have a top-level file that needs to be executed instead of a `Startup` with well known method names. I'd guess not. That's why you'd need `WebApplicationFactory` – Panagiotis Kanavos Jul 21 '22 at 13:35
  • `WebApplication.CreateBuilder` creates a plain old builder. It doesn't involve any extra customization or configuration nor does it care about `Startup` or `Program`. You could run your customization code on it, just like you do in `Program.cs`. Which means that if you extract your configuration code to a separate static method, you'll be able to apply it to that builder too. You won't need to create the `Program` class. That's only there for *WebApplicationFactory*. – Panagiotis Kanavos Jul 21 '22 at 13:39
  • Ok thanks for your time so far. But when I use WebApplicationFactory().UseStartup() I need to reference the 3 Program.cs files aswell. But that is not possible or am I seeing this wrong? – Brian Jul 21 '22 at 13:55

1 Answers1

0

You may change your Program classes adding different namespace to each one:

namespace Project1; // <- Note the namespaces here

public partial class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        //Add services , etc - the whole content of Program.cs
    }
}

As said here, there will be no side effects.


Daniel Oliveira
  • 1,101
  • 9
  • 26