-
-
Notifications
You must be signed in to change notification settings - Fork 794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mocked.Equals(mocked)
returns false by default if mocked class overrides Equals
#802
Comments
@stakx Thus, "fixing" the behavior means we'd get to remove a single line from that extension method. So absolutely no pressure from my side to fix this, but I also think it's good that you created the issue so if someone else has a problem with equals behavior he/she might find it ;-) |
Glad to hear that this isn't blocking you. But I'll still look into a bugfix. (Off-topic rumination: I had been thinking about a potential new feature for Moq that would give users the ability to register default implementations for whole interfaces. I was originally considering this in the context of people mocking Entity Framework |
There are three unit tests for (Click to expand and see the unit tests.)The last two tests hint at the distinction Moq makes between "partial mocks" and "full mocks":
Moq's provisioning of default
So any change we might make appears to make matters worse (less consistent) in some way. If we leave everything as is, we have at least some consistency, even though it 's not always sensible in cases such as the one that led to this issue being raised.
|
@stakx Generally I completely agree with you - with a twist. Nitpickers Corner
IMO it's not "a default implementation very close to" but rather it's 100% identical. It might seem like nitpicking but I think it's relevant. The TwistWhat's the reason to have loose mocks? We don't want to have to setup stuff which we don't care about = which are not relevant for the test.
If, however, we fail to setup something which is relevant for the test we've made a mistake. The test will fail, but observed symptom (failure message) might not directly point us to the missing setup. Now let me get back to the loose mock. Luckily moq has introduced a slight inconsistency and, as long as i don't override Imagine moq not having done so. How many times would you have had to setup Now let me get back to overridden And that's why I come back to my proposal of throwing an exception.
which, to me, seems an inconsistent but very much sensible design choice.
That could be very useful for implementing equality behavior. As I mentioned in another post, for "our" use case it would be very neat if we could register a custom default-setup for |
I've let this issue stew in the back of my mind for a while, yet I remain unsure how to resolve this best. I'll admit that However, I am fairly certain that introducing by-default strict mock behavior for |
Hi stakx Also, could there be cases where calling the base-implementation of |
Why? That would only be true if the mocked class had an implementation of My thinking was that if someone makes an effort to provide custom equality for a type, why shouldn't that equality behavior apply to a mock object like it does to any other instance?
Yes, but according to your earlier argument (that tests should explicitly set up |
That "none" in
was meant to relate to properties. Example:
Here, All of our classes have a constructor like
For the same reason as we're using a mock - and not the real thing - in the first place: I want to isolate my test from the actual behavior of the mocked class.
You may have tests where the equality of
Of course, in the test where equality is only needed for method call verifciation it can be simplified by:
A simpler explanation why I don't like it: adding an I'll quote Telerik:
|
It's been a while, and although your argument definitely has some merit, I don't feel comfortable making this change. Since you mentioned that this is not actually a roadblock for you, I'll close this issue. However, I'll mark it as unresolved in case someone else in the future wants to take another look at this. |
This is a follow-up to #791 (comment).
In the absence of any setup for
Equals
, Moq currently (attempts to) provide a default implementation that performs reference equality (as is the default in .NET for reference types). @BrunoJuchli discovered that when a mocked type overridesobject.Equals
, but does not provide a setup for it, then that default implementation will not execute:Reproduction code:
Actual behavior:
The second assertion (i.e. the one on
yMock
) fails.Expected behavior:
Both assertions should pass.
Possible solution:
In the following line:
https://github.com/moq/moq4/blob/bf19ad64540b9e3e71b8a869b2b1ab204ff1dbcb/src/Moq/Interception/InterceptionAspects.cs#L101
change
method.DeclaringType
tomethod.GetBaseDefinition().DeclaringType
.There's possible one or two other code locations where the same change would have to be applied. We should also try to keep the added runtime cost for this change minimal (if possible).
The text was updated successfully, but these errors were encountered: