Fix type matching for any() when parameter is Any (#1296)#1494
Fix type matching for any() when parameter is Any (#1296)#1494Raibaz merged 7 commits intomockk:masterfrom
Conversation
Introduce AnyTypedMatcher to ensure the any matcher correctly preserves type information. Refine the conditions for invoking TypedMatcher.checkType in InvocationMatcher to clarify null handling and type validation. Add test cases to verify the related behavior and improve stability. - Enforce strict type matching for any<T>() and any(KClass) - Support various type representations such as value classes - Strengthen type safety while maintaining backward compatibility - Add new tests to ensure reliability of the changes
Add tests to verify that any matchers behave correctly with proper type handling. - Validate type matching when using any<Int>() and any(Any::class) - Improve code reliability and test coverage
Remove unnecessary blank lines to improve code readability. Clean up the test code to keep its structure clear and consistent.
Split the constructor declaration of AnyTypedMatcher into multiple lines to improve readability. Align the class inheritance section by placing each interface on a separate line for better code consistency. Make the code easier to maintain and review.
What I changedI updated the behavior of Specifically:
The goal is to make Why this change is neededWith value classes, This change attempts to make the matcher more permissive and predictable Current issue / questionDuring this change, Before proceeding further, I would like to confirm:
I'm happy to adjust the implementation based on your preferred direction. |
|
If it's a new matcher type, it's correct for it to be included in the public API. You should be able to make the build pass by running |
Add the AnyTypedMatcher class to enable matching of arguments with various types. Implement the EquivalentMatcher, Matcher, and TypedMatcher interfaces to ensure consistent behavior. Include methods for type checking, copying, and substitution to allow more flexible test definitions.
|
Thanks! 😄 Confirmed it's a new matcher type. |
|
Thanks a lot for looking into this! Would you also please add documentation about the new matcher type here? |
Normalize markdown formatting in the README and fix typos. - Unify spacing and line breaks in tables, code blocks, and lists - Correct typos in several descriptions - Remove unnecessary blank lines to improve readability Improve overall consistency and readability of the documentation.
|
😄 Thanks for the suggestion. |
README.md
Outdated
| |---------------------------------------------------------|--------------------------------------------------------------------------------------------------------| | ||
| | `any()` | matches any argument | | ||
| | `any(Class)` | matches any argument of the give Class (for reflective mocking) | | ||
| | `any()` | matches any argument of type `T` (type-checked) | |
There was a problem hiding this comment.
Wouldn't this be clearer if the matcher was described as any<T>(), since you then refer to type T in the description?
There was a problem hiding this comment.
Thanks for pointing that out 👍😄 that makes sense.
Using any<T>() does read clearer given that the description refers to type T.
I’ll update the README to reflect this.
Update the documentation to describe using `any<T>()` for explicitly specifying the argument type. This improves clarity around type-checked matchers.
|
Thanks for following up on this! 🙏 |
Fixes: #1296
Problem
The
any<T>()andany(KClass)matchers do not respect the requested type whena mocked method parameter is declared as
Any.As a result, verifications such as
any<Int>()may incorrectly match argumentsof a different runtime type (e.g.
String), leading to false-positive matchesduring verification.
Solution
Introduce a type-aware matcher (
AnyTypedMatcher) for theanyfamily ofmatchers and apply type validation during invocation matching.
The solution:
any<T>()andany(KClass)their declared type
This fixes the incorrect matching behavior reported in #1296 while maintaining
existing semantics for other matchers.
Changes
AnyTypedMatcherto carry and validate type information forany<T>()andany(KClass)InvocationMatcherto invokeTypedMatcher.checkTypeonly fornon-null arguments
AnyTypedMatcherany<T>()andany(KClass)withAny-typed parameterscapturebehavior to ensure type safetyTests
Added
AnyMatcherTypeTestto verify:any<Int>()andany(Int::class)do not matchStringargumentsany(Any::class)capture-based type checksNote
Type-checking behavior for matchers other than
any()remains unchanged.Additional handling for Kotlin value classes is intentionally scoped to
AnyTypedMatcherto minimize side effects and preserve backward compatibility.