Reputation: 30534
I'm trying to mock a class using Mockito 1.9.5 but I'm having a lot of trouble getting it to work.
public class Property<T> {
private T value;
public T get() { return this.value; }
public void set(T value) { this.value = value; }
}
public class Model {
private final Property<Integer> count = new Property<Integer>();
public Property<Integer> count() { return this.count; }
}
public class View {
public View(Model model) {
Integer count = model.count().get();
}
}
I wrote my test boilerplate:
Model model = mock(Model.class, Mockito.RETURNS_MOCKS);
View view = new View(model);
... and got a long ClassCastException
:
Exception in thread "main" java.lang.ClassCastException: org.mockito.internal.creation.jmock.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$Enhancer
ByMockitoWithCGLIB$$cb6ca60b cannot be cast to java.lang.Integer
I know that Mockito can't mock final
classes or primitives, but I'm at a loss for what I need to do to make this work.
Upvotes: 0
Views: 5208
Reputation: 44042
The generic type of your class Property<Integer>
is erased during compilation. Mockito can only pick up the runtime type of your erased method. To Mockito, your class looks something like this:
public class Property {
private Object value;
public Object get() { return this.value; }
public void set(Object value) { this.value = value; }
}
When you mock this class, your call to model.count().get()
is implicitly cast to Integer
where this instruction is added by javac due to your generic information. However, Mockito only returns a mock of an Object
type after it observed the types above, thus the exception. Instead of
mock(Model.class, Mockito.RETURNS_MOCKS);
define the return value explicitly
mock(Model.class, Mockito.RETURNS_DEEP_STUBS); // intermediate mocks
when(model.count().get()).thenReturn(0);
The Integer
type is final and cannot be mocked which is why you need to return a dummy value.
Upvotes: 4