-
Notifications
You must be signed in to change notification settings - Fork 70
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
MethodMatcher can fail for restatement of generic method #15
Comments
Explanation: The full type is used to make the invocation that captures the expected method, and therefore the expectation captures the override/instantiation of the generic method. However, at runtime when called through the generic type, all generic parameters are actually treated as static type Object (thanks to type erasure). Concrete generic types have synthetic "bridge" methods that cast their Object-type parameters to the correct type and call the implementation. But bridge methods cannot be generated for interfaces. So, jMock will have to implement bridge methods itself, somehow. I don't think this can be done in the chain of Invokable objects created by the Mockery to implement basic object semantics for mock objects. So maybe it needs to be done when the expectation is created -- if the captured method is an instantiation of a generic method, mock the generic method as well. |
So I haven't had time to think through potential false positives, but MethodMatcher could be smarter to solve this problem? Something like public class MethodMatcher extends TypeSafeMatcher<Method> {
private Method expectedMethod;
...
@Override
public boolean matchesSafely(Method m) {
if (expectedMethod.equals(m))
return true;
if (!Modifier.isAbstract(expectedMethod.getModifiers()) || !Modifier.isAbstract(m.getModifiers()))
return false;
if (!expectedMethod.getName().equals(m.getName()))
return false;
if (!m.getDeclaringClass().isAssignableFrom(expectedMethod.getDeclaringClass()))
return false;
if (!m.getReturnType().isAssignableFrom(expectedMethod.getReturnType()))
return false;
if (!parametersAssignable(expectedMethod, m))
return false;
return true;
}
private boolean parametersAssignable(Method m1, Method m2) {
if (m1.getParameterTypes().length != m2.getParameterTypes().length)
return false;
for (int i = 0; i < m2.getParameterTypes().length; i++) {
if (!m2.getParameterTypes()[i].isAssignableFrom(m2.getParameterTypes()[i]))
return false;
}
return true;
}
} which passes all current tests and mine. |
Check resolved by #38 |
A bit subtle, but definitely confusing. If you reify a generic method in a sub-interface, then Java considers that a new declaredMethod. MethodMatcher only considers if the method called is .equals, rather than compatible...
... although I really don't know what compatible means. Anyhoo, this demonstrates the problem -
The text was updated successfully, but these errors were encountered: