I originally posted a question on the asp.net docs and was referred here.
Moving from NET5 -> NET6 broke a lot of testing using the WebApplicationFactory since the public Startup.cs was removed. The alternative was moving to Program which worked until the new templates came about. In the new templates there is no public class program, so we needed to add a public partial class Program {}
I was looking at the docs and they offered a new solution using InternalsVisibleTo which is better imho since it does not change code just for testing purposes.
However that would lead to code like this
public class UnitTest1 : IClassFixture<WebApplicationFactory<Program>>
{
public UnitTest1(WebApplicationFactory<Program> applicationFactory)
{
}
}
The problem however is that Program is internal, which triggers CS0051:
UnitTest1.cs(8, 12): [CS0051] Inconsistent accessibility: parameter type 'WebApplicationFactory' is less accessible than method 'UnitTest1.UnitTest1(WebApplicationFactory)')
The problem with that is that xunit requires its class / constructor to be public.
So did anyone manage to get this working without the public partial?
CodePudding user response:
If you just wanted to access the auto-generated internal
Program
class in your test project, [InternalsVisibleTo]
would work.
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>TestProject1</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
However, you're trying to use an internal
type as a type parameter to a public
type, and expect that public<internal>
type to be public
ly accessible.
Imagine a scenario with 3 assemblies: A
, B
, C
.
A
defines internal
class InternalImpl
and has [InternalsVisibleTo("B")]
set,
B
defines public
type as follows:
public class Container
{
public AnotherPublicType<InternalImpl> AnIllegalPublicProperty { get; }
// ...
}
In the above example, AnIllegalPublicProperty
is illegal, because though assembly B
has access to type InternalImpl
the type is still internal and wont be accessible to assembly C
(or any other assembly for that matter).
Infact, though AnotherPublicType
is a public class, C# would not allow AnotherPublicType<InternalImpl>
to be more accessible than internal, because the highest-allowed accessibility is the lowest accessibility of the type (AnotherPublicType
) and its type arguments (InternalImpl
). Changing that property to the following would work:
public class Container
{
internal AnotherPublicType<InternalImpl> AnIllegalPublicProperty { get; }
// ...
}
For more information, check the spec §7.5.3 Accessibility domains:
The accessibility domain for a constructed type T<A1, ..., Ae> is the intersection of the accessibility domain of the unbound generic type T and the accessibility domains of the type arguments A1, ..., Ae.
To answer your question, either WebApplicationFactory
must be made internal
(along with IClassFixture
and also UnitTest1
) or Program
must be made public
.
I believe xunit requires tests to be public.
So, your only option is to add the following to the end of your Program.cs
file:
#pragma warning disable CA1050 // Declare types in namespaces
public partial class Program { }
#pragma warning restore CA1050 // Declare types in namespaces