Description
When TUnit.Mocks generates an implementation for a method with an unconstrained generic type, it currently produces something like this:
public interface IFoo {
Task<T?> DoSomethingAsync<T>();
}
public sealed class IFooMock : global::TUnit.Mocks.Mock<global::Sandbox.IFoo>, IFoo
{
// ...
global::System.Threading.Tasks.Task<T?> global::Sandbox.IFoo.DoSomethingAsync<T>() => Object.DoSomethingAsync<T>();
}
Expected Behavior
When a generic is unconstrained, the default constraint should be added to the generated explicit interface implementation.
From https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters:
| Constraint |
Description |
where T : default |
This constraint resolves the ambiguity when you need to specify an unconstrained type parameter when you override a method or provide an explicit interface implementation. The default constraint implies the base method without either the class or struct constraint. For more information, see the default constraint spec proposal. |
Actual Behavior
The explicit interface implementation is generated without constraints and causes the error CS0453: The type parameter 'T' must be non-nullable value type in order to use it as underlying of 'System.Nullable<T>'. Consider adding a 'class' or 'default' constraint to allow using '?' as a nullable annotation.
Steps to Reproduce
using TUnit.Mocks.Generated.Sandbox;
namespace Sandbox;
public interface IFoo {
Task<T?> DoSomethingAsync<T>();
}
public class FooImpl : IFoo {
Task<T?> IFoo.DoSomethingAsync<T>() { // The type parameter 'T' must be non-nullable value type in order to use it as underlying of 'System.Nullable<T>'. Consider adding a 'class' or 'default' constraint to allow using '?' as a nullable annotation
return Task.FromResult<T?>(default);
}
Task<T?> IFoo.DoSomethingAsync<T>() where T : default { // No errors when using `default` constraint
return Task.FromResult<T?>(default);
}
}
public class TestClass {
[Test]
public async Task SomeTest() {
IFooMock mock = IFoo.Mock();
}
}
TUnit Version
1.24.31
.NET Version
.NET 10.0
Operating System
Windows
IDE / Test Runner
JetBrains Rider
Error Output / Stack Trace
Restore complete (0.8s)
Sandbox net10.0 failed with 5 error(s) (0.5s)
/mnt/x/Sandbox/Sandbox/obj/Debug/net10.0/TUnit.Mocks.SourceGenerator/TUnit.Mocks.SourceGenerator.MockGenerator/Sandbox_IFoo_Mock.g.cs(12,70): error CS0539: 'IFooMock.DoSomethingAsync<T>()' in explicit interface declaration is not found among members of the interface that can be implemented
/mnt/x/Sandbox/Sandbox/obj/Debug/net10.0/TUnit.Mocks.SourceGenerator/TUnit.Mocks.SourceGenerator.MockGenerator/Sandbox_IFoo_Mock.g.cs(6,84): error CS0535: 'IFooMock' does not implement interface member 'IFoo.DoSomethingAsync<T>()'
/mnt/x/Sandbox/Sandbox/obj/Debug/net10.0/TUnit.Mocks.SourceGenerator/TUnit.Mocks.SourceGenerator.MockGenerator/Sandbox_IFoo_Mock.g.cs(12,70): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable<T>'
Build failed with 5 error(s) in 1.7s
Additional Context
No response
IDE-Specific Issue?
Description
When
TUnit.Mocksgenerates an implementation for a method with an unconstrained generic type, it currently produces something like this:Expected Behavior
When a generic is unconstrained, the
defaultconstraint should be added to the generated explicit interface implementation.From https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters:
where T : defaultActual Behavior
The explicit interface implementation is generated without constraints and causes the error
CS0453:The type parameter 'T' must be non-nullable value type in order to use it as underlying of 'System.Nullable<T>'. Consider adding a 'class' or 'default' constraint to allow using '?' as a nullable annotation.Steps to Reproduce
TUnit Version
1.24.31
.NET Version
.NET 10.0
Operating System
Windows
IDE / Test Runner
JetBrains Rider
Error Output / Stack Trace
Additional Context
No response
IDE-Specific Issue?
dotnet testordotnet run, not just in my IDE