-
Notifications
You must be signed in to change notification settings - Fork 279
Open
Labels
bugReported problem with NSubstitute behaviourReported problem with NSubstitute behaviour
Description
Describe the bug
I am suspecting that something is not working well with argument matchers that matches structs with a field with non-default value initializer. Maybe I am doing something wrong - int this case please point me to the right direction :)
To Reproduce
using NSubstitute;
var service = Substitute.For<IService>();
var executor = new ExecutorService(service);
executor.Execute();
service.Received(1).DoSomething(Arg.Any<StructObject>());
//service.Received(1).DoSomething(Arg.Is<StructObject>(static a => a.Index > 0)); // I tried Arg.Is<> but is does not change anything
public interface IService
{
void DoSomething(StructObject objA);
}
public class ExecutorService
{
private readonly IService _service;
public ExecutorService(IService service)
{
_service = service;
}
public void Execute()
{
var objInstance = new StructObject
{
Index = 5
};
_service.DoSomething(objInstance);
}
}
public struct StructObject
{
public required int Index { get; init; } = -1;
public StructObject()
{
}
}Expected behaviour
I think is should just match provided object's instance. Instead of that I am getting exception below:
Unhandled exception. NSubstitute.Exceptions.RedundantArgumentMatcherException: Some argument specifications (e.g. Arg.Is, Arg.Any) were left over after the last call.
This is often caused by using an argument spec with a call to a member NSubstitute does not handle (such as a non-virtual member or a call to an instance which is not a substitute), or for a purpose other than specifying a call (such as using an arg spec as a return value). For example:
var sub = Substitute.For<SomeClass>();
var realType = new MyRealType(sub);
// INCORRECT, arg spec used on realType, not a substitute:
realType.SomeMethod(Arg.Any<int>()).Returns(2);
// INCORRECT, arg spec used as a return value, not to specify a call:
sub.VirtualMethod(2).Returns(Arg.Any<int>());
// INCORRECT, arg spec used with a non-virtual method:
sub.NonVirtualMethod(Arg.Any<int>()).Returns(2);
// CORRECT, arg spec used to specify virtual call on a substitute:
sub.VirtualMethod(Arg.Any<int>()).Returns(2);
To fix this make sure you only use argument specifications with calls to substitutes. If your substitute is a class, make sure the member is virtual.
Another possible cause is that the argument spec type does not match the actual argument type, but code compiles due to an implicit cast. For example, Arg.Any<int>() was used, but Arg.Any<double>() was required.
NOTE: the cause of this exception can be in a previously executed test. Use the diagnostics below to see the types of any redundant arg specs, then work out where they are being created.
Diagnostic information:
Remaining (non-bound) argument specifications:
any StructObject
All argument specifications:
any StructObject
To get rid of the exception I can do one of the things below:
- change StructObject to become a class
- remove Index property initializer (or make it equal to 0)
Environment:
- NSubstitute version: 5.1.0
- Platform: .net8 on windows
Additional context
I reproduced this case with the Moq library and it works fine.
Argument matcher for a struct with a field with non-default value
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugReported problem with NSubstitute behaviourReported problem with NSubstitute behaviour