Skip to content
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

Make guard against unmatchable matchers less strict to enable user-based wildcard matching #1202

Merged
merged 5 commits into from Aug 23, 2021

Conversation

adamfk
Copy link
Contributor

@adamfk adamfk commented Aug 21, 2021

All tests are passing. No changes to moq API. I think we might have it!

Resolves #1199.

Copy link
Contributor

@stakx stakx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to see you got this working! 👍

In addition to the change requests below, please also add an entry to the changelog, e.g.:

 #### Fixed
 ...
+* The guard against unmatchable matchers (added in #900) was too strict; relaxed it to enable an alternative user-code shorthand `_` for `It.IsAny<>()` (@adamfk, #1199)


 ## 4.16.1 (2021-02-23)

src/Moq/MatcherFactory.cs Outdated Show resolved Hide resolved
src/Moq/MatcherFactory.cs Outdated Show resolved Hide resolved
Comment on lines 108 to 111
else
{
foundType = convertExpression.Operand.Type;
}
Copy link
Contributor

@stakx stakx Aug 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Ideally, we wouldn't have any conditionals here. We ought to be able to simply ask the Match object directly what type of values it targets.

I also suspect that we currently don't have any tests covering this else block.

For both reasons, it'd be nice to simplify this whole ifelse block to something non-conditional, but this is more of a bonus—you can leave this code as is for now.)

Copy link
Contributor Author

@adamfk adamfk Aug 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't mind making a new ticket to clean it up. I'd like to get this in and working first.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are willing to clean this up, then I say, let's do it now. (It should be a fairly trivial change, see my earlier comment over in the issue about adding some Type property to Match.)

src/Moq/MatcherFactory.cs Show resolved Hide resolved
src/Moq/MatcherFactory.cs Outdated Show resolved Hide resolved
tests/Moq.Tests/Matchers/AnyValueAttributeTests3.cs Outdated Show resolved Hide resolved
@stakx stakx changed the title Enable support for user based wildcard matching #1199 Enable support for user based wildcard matching Aug 21, 2021
@stakx stakx changed the title Enable support for user based wildcard matching Make guard against unmatchable matchers less strict to enable user-based wildcard matching Aug 21, 2021
@stakx stakx added this to the 4.17.0 milestone Aug 21, 2021
Copy link
Contributor

@stakx stakx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please roll back your last commit that extracts the assignment compatibility check into a method and adds tests for it.

I'm generally all for more tests, but I think it really isn't necessary to test Type.IsAssignableFrom... too low-level. Also, there is already UnmatchableMatchersFixture that targets this particular bit of Moq.

@adamfk
Copy link
Contributor Author

adamfk commented Aug 21, 2021

Please roll back your last commit that extracts the assignment compatibility check into a method and adds tests for it.

@stakx Done. I just added it so that I could show that the original parameter.ParameterType.IsAssignableFrom(matchedValuesType) was correct.

I've used bitbucket a lot at work, but this is my first github PR. Do you get notified to my conversation replies like this one #1202 (comment), or do I need to explicitly tag you?

@stakx
Copy link
Contributor

stakx commented Aug 22, 2021

Do you get notified to my conversation replies like this one #1202 (comment), or do I need to explicitly tag you?

GitHub notifies me whenever there is any change to the PR, be it a new commit or a new comment somewhere... it's then up to me to locate the change(s). Not the best possible notification system, really, but it's what we have to work with. 🙂

Copy link
Contributor

@stakx stakx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good to be merged! 🚀

Did you want to work on the conditional re: matchedValuesType now, or some other time?

Copy link
Contributor Author

@adamfk adamfk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you want to work on the conditional re: matchedValuesType now, or some other time?

I'd rather start on a source generator for wild card matching. Thanks again for all the help getting this bug fixed! 😃

public static implicit operator Animal(AnyValue _) => It.IsAny<Animal>();
public static implicit operator Dolphin(AnyValue _) => It.IsAny<Dolphin>();
public static implicit operator int(AnyValue _) => default;
public static implicit operator byte(AnyValue _) => default;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stakx should I switch these back to using It.IsAny<T>()? Or should I rely on implicit conversion functions like this never being called? Just thinking about making a source generator for people to use and if possible, I don't want to rely on behavior that may be changed.

Copy link
Contributor

@stakx stakx Aug 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, keep these as default. You should only have one call to a matcher per parameter. If you have more than that, you may confuse the SetupSet / VerifySet delegate reconstruction machinery (ActionObserver), which attempts to distribute recorded matchers over the available parameters.

Note also this comment in ActionObserver, which states Moq's general assumption of matchers returning default(T):

https://github.com/moq/moq4/blob/abc05532d7350c5431a5d89a91b667d569fa4d65/src/Moq/ActionObserver.cs#L127-L128

Meaning, if you want SetupSet and VerifySet to interact correctly with your _ shorthand, it should probably return default / null instead of new AnyValue().

@stakx stakx merged commit b8518de into devlooped:main Aug 23, 2021
@stakx
Copy link
Contributor

stakx commented Aug 23, 2021

Thanks for contributing, @adamfk!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

implicit guard too strict; prevents valid user wildcard _ implementations
2 participants