WebApplicationFactory does not work from when CreateHostBuilder is from another class + assembly, instead of the entry point assembly.
See original GitHub issueRelated
This issue is related to #8210 and (archived) Hosting #1517
Problem
The WebApplicationFactory doesn’t work right when the “entry point assembly” references another assembly which contains the CreateHostBuilder logic. Current code (I think) requires a method called CreateHostBuilder to exist in the entry point assembly, only.
Repo
A full repo of this problem can be found here in GitHub.
Description
I have a pretty standard ASP.NET Core 3.1 web api application and i’m trying to use the WebAppFactory to test my web application.
For my program.cs file, instead of adding my custom code in there (e.g. wire up Serilog, etc), I actually have a nuget package which I then re-use everywhere. So if I change my program.cs logic, I can just update various webapi applications with the latest nuget, instead of having to change the copy/paste code in each webapi program.cs class. Works really well.
Given this type of setup, the WebApplicationFactory fails to ResolveHostBuilderFactory because the entry point assembly doesn’t contain the CreateHostBuilder<T> method. And therefore stuff isn’t working 100% right.
For example.
this is my program.cs
public class Program
{
public static Task Main()
{
var options = new MainOptions
{
FirstLoggingInformationMessage = "~~~ Starting FooBar Web Api ~~~"
};
return Homely.AspNetCore.Hosting.CoreApp.Program.Main<Startup>(options);
}
}
That’s it. Notice how it’s very different to the default template on first glance. So my program.cs class literally says: -> call some other assembly’s Main method and do stuff. It’s this other Main<T>(..) method that contains the typical template logic.
(That Main method logic is literally -> setup Serilog, do the normal program.cs templated stuff … then flush the Serilog on exit. So just logging plumbing wrapped around the default program.cs Main logic).
Okay - so my entry point assembly just calls some other assembly. Nothing crazy.
Except … it doesn’t work in this case because the WebApplicationFactory.CreateHostBuilder() code does this…
protected virtual IHostBuilder CreateHostBuilder()
{
var hostBuilder = HostFactoryResolver.ResolveHostBuilderFactory<IHostBuilder>(typeof(TEntryPoint).Assembly)?.Invoke(Array.Empty<string>());
<snip>
}
and that RHBF method then does this …
public static Func<string[], THostBuilder> ResolveHostBuilderFactory<THostBuilder>(Assembly assembly)
{
return ResolveFactory<THostBuilder>(assembly, CreateHostBuilder);
}
private static Func<string[], T> ResolveFactory<T>(Assembly assembly, string name)
{
var programType = assembly?.EntryPoint?.DeclaringType;
if (programType == null)
{
return null;
}
<snip>
}
and the assembly?.EntryPoint?.DeclaringType ends up returning null. Sadness 😦
So … I’m not sure what can be done here, for this scenario. It’s like I wish the code could ‘see’ that the entry point assembly is not the right place to check, but another assembly which I tell it, is what should be checked.
Secondly, I also tried this:
public class WebAppFactory : WebApplicationFactory<Homely.AspNetCore.Hosting.CoreApp.Program>
but that errored with: System.InvalidOperationException : The provided Type 'Program' does not belong to an assembly with an entry point. A common cause for this error is providing a Type from a class library. That’s exactly what I’m trying to do, though 😛
So - would love some help, please?
$ dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 3.1.100
Commit: cd82f021f4
Runtime Environment:
OS Name: Windows
OS Version: 10.0.18362
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\3.1.100\
Host (useful for support):
Version: 3.1.0
Commit: 65f04fb6db
Issue Analytics
- State:
- Created 4 years ago
- Reactions:11
- Comments:10 (8 by maintainers)

Top Related StackOverflow Question
We’ve moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
.NET 6