NSubstitute
NSubstitute copied to clipboard
Difference in Received() check between array params and new C# 13 params
C# 13 allows using params with many collection types. https://devblogs.microsoft.com/dotnet/csharp13-calling-methods-is-easier-and-faster/
Example:
void DoSomething2(params IEnumerable<object> values) {}
DoSomething2(new object(), new object());
The compiler will automatically create the required collection. This causes an inconsistency between checking with classic array params and the new collections params:
public interface ITest
{
void DoSomething(params object[] args);
void DoSomething2(params IEnumerable<object> values); // valid since C# 13
}
public class Test
{
public static void Run()
{
var obj = new Object();
var substitute = Substitute.For<ITest>();
substitute.DoSomething(obj);
substitute.DoSomething2(obj);
// Works
substitute.Received().DoSomething(obj);
// Fails
substitute.Received().DoSomething2(obj);
// Works, but verbose
substitute.Received()
.DoSomething2(Arg.Is<IEnumerable<object>>(args => args.SequenceEqual(new List<object> { obj })));
/*
* NSubstitute.Exceptions.ReceivedCallsException: Expected to receive a call matching:
* DoSomething2(<>z__ReadOnlySingleElementList<Object>)
* Actually received no matching calls.
* Received 1 non-matching call (non-matching arguments indicated with '*' characters):
* DoSomething2(*<>z__ReadOnlySingleElementList<Object>*)
*/
}
}
I wouldn't call it a bug but this is certainly unexpected. Is there a simpler way to do the check?