Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions TUnit.Mocks.SourceGenerator.Tests/MockGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,66 @@ void M()
return VerifyGeneratorOutput(source);
}

[Test]
public Task Method_With_More_Params_Than_Func_Action_Arity()
{
// Issue #6254: an async method with more parameters than the BCL Func<>/Action<> arity
// limit (16 inputs) must not emit typed Returns/ReturnsAsync/Callback/Throws overloads —
// doing so produced CS0305. The wrapper is still generated (for the untyped ReturnsAsync
// surface); only the parameter-typed convenience overloads are omitted.
var source = """
using System.Threading.Tasks;
using TUnit.Mocks;

public interface ILongMethodSignatures
{
Task SomeMethod(string _1, string _2, string _3, string _4, string _5,
string _6, string _7, string _8, string _9, string _10,
string _11, string _12, string _13, string _14, string _15,
string _16, string _17, string _18, string _19, string _20);
}

public class TestUsage
{
void M()
{
var mock = Mock.Of<ILongMethodSignatures>();
}
}
""";

return VerifyGeneratorOutput(source);
}

[Test]
public Task Returning_Async_Method_With_More_Params_Than_Func_Action_Arity()
{
// Issue #6254, returning-async (Task<T>) variant. This routes through the value-returning
// unified-class emit path (distinct from the void-Task path above), which has its own
// arity gate. At 17 params — one past the BCL Func<>/Action<> limit — the typed overloads
// must be omitted while the untyped Returns/ReturnsAsync surface is retained.
var source = """
using System.Threading.Tasks;
using TUnit.Mocks;

public interface ILongReturningSignature
{
Task<int> Sum(int _1, int _2, int _3, int _4, int _5, int _6, int _7, int _8, int _9,
int _10, int _11, int _12, int _13, int _14, int _15, int _16, int _17);
}

public class TestUsage
{
void M()
{
var mock = Mock.Of<ILongReturningSignature>();
}
}
""";

return VerifyGeneratorOutput(source);
}

[Test]
public Task GenerateMock_Attribute_With_Concrete_Class()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
// <auto-generated/>
#pragma warning disable
#nullable enable

public sealed class ILongMethodSignaturesMock : global::TUnit.Mocks.Mock<global::ILongMethodSignatures>, global::ILongMethodSignatures
{
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
internal ILongMethodSignaturesMock(global::ILongMethodSignatures mockObject, global::TUnit.Mocks.MockEngine<global::ILongMethodSignatures> engine)
: base(mockObject, engine) { }

global::System.Threading.Tasks.Task global::ILongMethodSignatures.SomeMethod(string _1, string _2, string _3, string _4, string _5, string _6, string _7, string _8, string _9, string _10, string _11, string _12, string _13, string _14, string _15, string _16, string _17, string _18, string _19, string _20) => Object.SomeMethod(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20);
}


// ===== FILE SEPARATOR =====

// <auto-generated/>
#pragma warning disable
#nullable enable

file sealed class ILongMethodSignaturesMockImpl : global::ILongMethodSignatures, global::TUnit.Mocks.IRaisable, global::TUnit.Mocks.IMockObject
{
private readonly global::TUnit.Mocks.MockEngine<global::ILongMethodSignatures> _engine;

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
global::TUnit.Mocks.IMock? global::TUnit.Mocks.IMockObject.MockWrapper { get; set; }

internal ILongMethodSignaturesMockImpl(global::TUnit.Mocks.MockEngine<global::ILongMethodSignatures> engine)
{
_engine = engine;
}

public global::System.Threading.Tasks.Task SomeMethod(string _1, string _2, string _3, string _4, string _5, string _6, string _7, string _8, string _9, string _10, string _11, string _12, string _13, string _14, string _15, string _16, string _17, string _18, string _19, string _20)
{
try
{
_engine.HandleCall(0, "SomeMethod", new object?[] { _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20 });
if (global::TUnit.Mocks.Setup.RawReturnContext.TryConsume(out var __rawAsync))
{
if (__rawAsync is global::System.Threading.Tasks.Task __typedAsync) return __typedAsync;
throw new global::System.InvalidOperationException($"ReturnsAsync: expected global::System.Threading.Tasks.Task but got {__rawAsync?.GetType().Name ?? "null"}");
}
return global::System.Threading.Tasks.Task.CompletedTask;
}
catch (global::System.Exception __ex)
{
return global::System.Threading.Tasks.Task.FromException(__ex);
}
}

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public void RaiseEvent(string eventName, object? args)
{
throw new global::System.InvalidOperationException($"No event named '{eventName}' exists on this mock.");
}
}

internal static class ILongMethodSignaturesMockFactory
{
[global::System.Runtime.CompilerServices.ModuleInitializer]
internal static void Register()
{
global::TUnit.Mocks.MockRegistry.RegisterFactory<global::ILongMethodSignatures>(Create);
}

internal static global::TUnit.Mocks.Mock<global::ILongMethodSignatures> CreateAutoMock(global::TUnit.Mocks.MockBehavior behavior)
{
var engine = new global::TUnit.Mocks.MockEngine<global::ILongMethodSignatures>(behavior);
var impl = new ILongMethodSignaturesMockImpl(engine);
engine.Raisable = impl;
var mock = new ILongMethodSignaturesMock(impl, engine);
return mock;
}

internal static global::TUnit.Mocks.Mock<global::ILongMethodSignatures> Create(global::TUnit.Mocks.MockBehavior behavior, object[] constructorArgs)
{
if (constructorArgs.Length > 0) throw new global::System.ArgumentException($"Interface mock 'global::ILongMethodSignatures' does not support constructor arguments, but {constructorArgs.Length} were provided.");
var engine = new global::TUnit.Mocks.MockEngine<global::ILongMethodSignatures>(behavior);
var impl = new ILongMethodSignaturesMockImpl(engine);
engine.Raisable = impl;
var mock = new ILongMethodSignaturesMock(impl, engine);
return mock;
}
}


// ===== FILE SEPARATOR =====

// <auto-generated/>
#pragma warning disable
#nullable enable

public static class ILongMethodSignatures_MockMemberExtensions
{
public static ILongMethodSignatures_SomeMethod_M0_MockCall SomeMethod(this global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock, global::TUnit.Mocks.Arguments.Arg<string> _1, global::TUnit.Mocks.Arguments.Arg<string> _2, global::TUnit.Mocks.Arguments.Arg<string> _3, global::TUnit.Mocks.Arguments.Arg<string> _4, global::TUnit.Mocks.Arguments.Arg<string> _5, global::TUnit.Mocks.Arguments.Arg<string> _6, global::TUnit.Mocks.Arguments.Arg<string> _7, global::TUnit.Mocks.Arguments.Arg<string> _8, global::TUnit.Mocks.Arguments.Arg<string> _9, global::TUnit.Mocks.Arguments.Arg<string> _10, global::TUnit.Mocks.Arguments.Arg<string> _11, global::TUnit.Mocks.Arguments.Arg<string> _12, global::TUnit.Mocks.Arguments.Arg<string> _13, global::TUnit.Mocks.Arguments.Arg<string> _14, global::TUnit.Mocks.Arguments.Arg<string> _15, global::TUnit.Mocks.Arguments.Arg<string> _16, global::TUnit.Mocks.Arguments.Arg<string> _17, global::TUnit.Mocks.Arguments.Arg<string> _18, global::TUnit.Mocks.Arguments.Arg<string> _19, global::TUnit.Mocks.Arguments.Arg<string> _20)
{
var matchers = new global::TUnit.Mocks.Arguments.IArgumentMatcher[] { _1.Matcher, _2.Matcher, _3.Matcher, _4.Matcher, _5.Matcher, _6.Matcher, _7.Matcher, _8.Matcher, _9.Matcher, _10.Matcher, _11.Matcher, _12.Matcher, _13.Matcher, _14.Matcher, _15.Matcher, _16.Matcher, _17.Matcher, _18.Matcher, _19.Matcher, _20.Matcher };
return new ILongMethodSignatures_SomeMethod_M0_MockCall(global::TUnit.Mocks.MockRegistry.GetEngine(mock), 0, "SomeMethod", matchers);
}

/// <summary>Configure the mock setup for <c>SomeMethod</c> with every argument matched as <c>Any&lt;T&gt;()</c>.</summary>
public static ILongMethodSignatures_SomeMethod_M0_MockCall SomeMethod(this global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock, global::TUnit.Mocks.Arguments.AnyArgs _)
{
var matchers = new global::TUnit.Mocks.Arguments.IArgumentMatcher[] { global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance, global::TUnit.Mocks.Matchers.AnyMatcher<string>.Instance };
return new ILongMethodSignatures_SomeMethod_M0_MockCall(global::TUnit.Mocks.MockRegistry.GetEngine(mock), 0, "SomeMethod", matchers);
}

#if NET9_0_OR_GREATER
[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public static void Reset(this global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock)
=> global::TUnit.Mocks.Mock.Reset(mock);

[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public static void VerifyAll(this global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock)
=> global::TUnit.Mocks.Mock.VerifyAll(mock);

[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public static void VerifyNoOtherCalls(this global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock)
=> global::TUnit.Mocks.Mock.VerifyNoOtherCalls(mock);

[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public static void SetupAllProperties(this global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock)
=> global::TUnit.Mocks.Mock.SetupAllProperties(mock);

[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public static global::TUnit.Mocks.Diagnostics.MockDiagnostics GetDiagnostics(this global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock)
=> global::TUnit.Mocks.Mock.GetDiagnostics(mock);

[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public static void SetState(this global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock, string? stateName)
=> global::TUnit.Mocks.Mock.SetState(mock, stateName);

[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public static void InState(this global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock, string stateName, global::System.Action<global::TUnit.Mocks.Mock<global::ILongMethodSignatures>> configure)
=> global::TUnit.Mocks.Mock.InState(mock, stateName, configure);

extension(global::TUnit.Mocks.Mock<global::ILongMethodSignatures> mock)
{
[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public global::System.Collections.Generic.IReadOnlyList<global::TUnit.Mocks.Verification.CallRecord> Invocations => global::TUnit.Mocks.Mock.Invocations(mock);

[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public global::TUnit.Mocks.MockBehavior Behavior => global::TUnit.Mocks.Mock.Behavior(mock);

[global::System.Runtime.CompilerServices.OverloadResolutionPriority(-1)]
public global::TUnit.Mocks.IDefaultValueProvider? DefaultValueProvider
{
get => global::TUnit.Mocks.Mock.GetDefaultValueProvider(mock);
set => global::TUnit.Mocks.Mock.SetDefaultValueProvider(mock, value);
}
}
#endif
}

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public sealed class ILongMethodSignatures_SomeMethod_M0_MockCall : global::TUnit.Mocks.Verification.ICallVerification
{
private readonly global::TUnit.Mocks.IMockEngineAccess _engine;
private readonly int _memberId;
private readonly string _memberName;
private readonly global::TUnit.Mocks.Arguments.IArgumentMatcher[] _matchers;
private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder? _builder;

internal ILongMethodSignatures_SomeMethod_M0_MockCall(global::TUnit.Mocks.IMockEngineAccess engine, int memberId, string memberName, global::TUnit.Mocks.Arguments.IArgumentMatcher[] matchers)
{
_engine = engine;
_memberId = memberId;
_memberName = memberName;
_matchers = matchers;
_ = EnsureSetup();
}

private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetup()
{
var existing = global::System.Threading.Volatile.Read(ref _builder);
if (existing is not null) return existing;
return EnsureSetupSlow();
}

[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
private global::TUnit.Mocks.Setup.VoidMethodSetupBuilder EnsureSetupSlow()
{
var setup = new global::TUnit.Mocks.Setup.MethodSetup(_memberId, _matchers, _memberName);
var fresh = new global::TUnit.Mocks.Setup.VoidMethodSetupBuilder(setup);
var prev = global::System.Threading.Interlocked.CompareExchange(ref _builder, fresh, null);
if (prev is not null) return prev;
// AddSetup runs only on the CAS winner. Setup is sequential in practice,
// so a concurrent loser observing the builder before registration is benign.
_engine.AddSetup(setup);
return fresh;
}

/// <inheritdoc />
public ILongMethodSignatures_SomeMethod_M0_MockCall Returns() { EnsureSetup().Returns(); return this; }
/// <inheritdoc />
public ILongMethodSignatures_SomeMethod_M0_MockCall Throws<TException>() where TException : global::System.Exception, new() { EnsureSetup().Throws<TException>(); return this; }
/// <inheritdoc />
public ILongMethodSignatures_SomeMethod_M0_MockCall Throws(global::System.Exception exception) { EnsureSetup().Throws(exception); return this; }
/// <inheritdoc />
public ILongMethodSignatures_SomeMethod_M0_MockCall Callback(global::System.Action callback) { EnsureSetup().Callback(callback); return this; }
/// <inheritdoc />
public ILongMethodSignatures_SomeMethod_M0_MockCall TransitionsTo(string stateName) { EnsureSetup().TransitionsTo(stateName); return this; }
/// <inheritdoc />
public ILongMethodSignatures_SomeMethod_M0_MockCall Then() { EnsureSetup().Then(); return this; }

/// <summary>Return a pre-built Task directly (e.g., from a TaskCompletionSource).</summary>
public ILongMethodSignatures_SomeMethod_M0_MockCall ReturnsAsync(global::System.Threading.Tasks.Task task) { EnsureSetup().ReturnsRaw(task); return this; }
/// <summary>Return a pre-built Task from a factory, invoked on each call.</summary>
public ILongMethodSignatures_SomeMethod_M0_MockCall ReturnsAsync(global::System.Func<global::System.Threading.Tasks.Task> taskFactory) { EnsureSetup().ReturnsRaw(() => (object?)taskFactory()); return this; }

// ICallVerification
/// <inheritdoc />
public void WasCalled() => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled();
/// <inheritdoc />
public void WasCalled(global::TUnit.Mocks.Times times) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled(times);
/// <inheritdoc />
public void WasCalled(global::TUnit.Mocks.Times times, string? message) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled(times, message);
/// <inheritdoc />
public void WasCalled(string? message) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasCalled(message);
/// <inheritdoc />
public void WasNeverCalled() => _engine.CreateVerification(_memberId, _memberName, _matchers).WasNeverCalled();
/// <inheritdoc />
public void WasNeverCalled(string? message) => _engine.CreateVerification(_memberId, _memberName, _matchers).WasNeverCalled(message);
}


// ===== FILE SEPARATOR =====

// <auto-generated/>
#pragma warning disable
#nullable enable

namespace TUnit.Mocks
{
public static class ILongMethodSignatures_MockStaticExtension
{
extension(global::ILongMethodSignatures _)
{
public static global::ILongMethodSignaturesMock Mock()
{
return (global::ILongMethodSignaturesMock)global::ILongMethodSignaturesMockFactory.CreateAutoMock(global::TUnit.Mocks.Mock.DefaultBehavior);
}

public static global::ILongMethodSignaturesMock Mock(global::TUnit.Mocks.MockBehavior behavior)
{
return (global::ILongMethodSignaturesMock)global::ILongMethodSignaturesMockFactory.CreateAutoMock(behavior);
}
}
}
}


// ===== FILE SEPARATOR =====

// <auto-generated/>
#pragma warning disable
#nullable enable

namespace TUnit.Mocks.Generated;
Loading
Loading