Issue
I currently have a unit test that runs fine using EasyMock 3.4, but when I try to compile and run it using EasyMock 4.0.2 I noticed a weird behavior that I don't really understand:
I have a class with two methods as below (notice the signature change):
public TestAccessSource setAccess(Class<?> clazz, Object access) {
return setAccess(clazz.getName(), access);
}
public TestAccessSource setAccess(Class<?> clazz, InterfaceA access) {
return setAccess(clazz, (Object) access);
}
I'm invoking the setAccess
method in my unit test as below:
testSources.setAccess(InterfaceB.class, EasyMock.createNiceMock(InterfaceB.class));
In 3.4 the setAccess
method with Object
as second argument is invoked, and in 4.0.2 the setAccess
method with the InterfaceA
as second argument is invoked, throwing a java.lang.ClassCastException
, as the interfaces are not related - The only thing they have in common is that they extend the Remote
interface.
If I simply use an implementation of InterfaceB
instead of mocking it, the correct setAccess
method is invoked:
testSources.setAccess(InterfaceB.class, new InterfaceB(){});
Here is the full working example to reproduce the behavior. The first setAccess
works, but the second fails. Both work fine when running on EasyMock 3.4:
public class TestEasyMockBehavior {
public static void main(String[] args) {
TestAccessSource testSources = new TestAccessSource();
testSources.setAccess(InterfaceB.class, new InterfaceB(){});
testSources.setAccess(InterfaceB.class, EasyMock.createNiceMock(InterfaceB.class));
}
public static class TestAccessSource {
public TestAccessSource setAccess(Class<?> clazz, Object access) {
return setAccess(clazz.getName(), access);
}
public TestAccessSource setAccess(Class<?> clazz, InterfaceA access) {
return setAccess(clazz, (Object) access);
}
public TestAccessSource setAccess(String key, Object access) {
System.out.println(key + " - " + access.getClass().getName());
return this;
}
}
public interface InterfaceA extends Remote {}
public interface InterfaceB extends Remote {}
}
I am looking for some help to understand why it is happening and what exactly changed. I could not find any questions related to this behavior.
Solution
It's related EasyMock 4 not Java 11. Indeed, I changed the typing for EasyMock 4. Before it was T mock(Class<T>)
. Which is really annoying because as soon as you want to do List<String> list = (List) mock(List.class)
you get a warning.
So I decided to type T mock(Class<?>)
. Problem solved, the type is inferred.
The drawback is that in some cases it isn't inferred or, more rarely, correctly inferred. But these cases are according to me exceptional because in general you assign the mock to a variable to be able to record stuff and then replay.
To solve your problem you have two solutions:
testSources.setAccess(InterfaceB.class, (InterfaceB) mock(InterfaceB.class));
testSources.setAccess(InterfaceB.class, EasyMock.<InterfaceB>mock(InterfaceB.class));
Answered By - Henri
Answer Checked By - Mildred Charles (JavaFixing Admin)