NSubstitute and Structs that implements Equals

179 views
Skip to first unread message

Bruno Silva

unread,
Jan 3, 2020, 8:06:38 AM1/3/20
to NSubstitute
Hey,

I'm facing problems with NSubstitute when I have a struct, as a method argument, that implements Equals.
The configuration of problem is as the following:

public class Caller
    {
        public virtual String Method(Argument arg)
        {
            throw new NotImplementedException();
        }
    }

    public struct Argument
    {
        // override object.Equals
        public override bool Equals(object obj)
        {
            throw new NotImplementedException();
        }

        // override object.GetHashCode
        public override int GetHashCode()
        {
            throw new NotImplementedException();
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            Caller mock = NSubstitute.Substitute.ForPartsOf<Caller>();
            var arg = NSubstitute.Arg.Any<Argument>();
            mock.Method(arg).Returns("Okey!");
            Console.Write(mock.Method(new Argument()));
            Console.ReadKey();
        }
    }

The problem is that the Equals method is hitted and the exception is throw.
Is there anything that can be done to overpass this?

David Tchepak

unread,
Jan 3, 2020, 9:09:13 PM1/3/20
to nsubs...@googlegroups.com
Hi Bruno,

NSubstitute uses equality to work out which arguments and argument matchers to use for each method parameter. Unfortunately there is no way to work around this with NSubstitute. .NET relies on having valid Equals and GetHashCode implementations for a number of fundamental cases, so this is generally a safe assumption for libraries to make. (We've previously tried allowing stubbing these values, but found it caused a number of unintended problems interacting with .NET [1])

If you can expand a bit on what you're trying to do I'm happy to try to assist finding another approach.

Regards,
David


--
You received this message because you are subscribed to the Google Groups "NSubstitute" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nsubstitute...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nsubstitute/af3773ab-93e8-4289-a380-6618532939d5%40googlegroups.com.

Bruno Silva

unread,
Jan 6, 2020, 7:22:49 AM1/6/20
to NSubstitute
Hi David,

thank you for your reply. We have a struct that implements Equals method, and it is a little bit different from the usual.
But something that attracted my attention is the fact that it occurs only when I used struct. When I changed to use class it didn't occur, the method Equals was not called.
It's something particular for structs?

Regards,
Bruno.
To unsubscribe from this group and stop receiving emails from it, send an email to nsubs...@googlegroups.com.

David Tchepak

unread,
Jan 6, 2020, 6:58:02 PM1/6/20
to nsubs...@googlegroups.com
The stack trace from the sample code includes `System.Collections.Generic.ObjectEqualityComparer`1.Equals(T x, T y)`. I'm guessing this uses reference equality for reference types, but structs require value equality [1] so `.Equals` gets called.

Hope this helps. :)


To unsubscribe from this group and stop receiving emails from it, send an email to nsubstitute...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nsubstitute/7aed05b1-5028-4816-a038-1e1c562be144%40googlegroups.com.

Bruno Silva

unread,
Jan 8, 2020, 7:44:20 AM1/8/20
to NSubstitute
David, thank you a lot for your prompt answer.
We are overpass this problem with ReturnsForAnyArgs.
Thank you!
Reply all
Reply to author
Forward
0 new messages