So I my previous was not relevant to actual problem. Though the answer still holds true such exception happens when a mock using deep stubs answer returns a mock.
So what is the real issue, it's still caused by generics and type erasure. You have two different classes:
The test:
public class ProcessorTest extends AbstractProcessorTest<Processor, ProcessAlpha>
And the parent of the test :
public abstract class AbstractProcessorTest<P extends AbstractProcessor<T>, T extends AbstractProcess> {
@Mock(answer = ...)
protected P processor;
- So the compiler will first compile
AbstractProcessorTest, when doing so it will see that P is in fact an AbstractProcessor, and it will compile the class this way.
- Then the compiler will compile
ProcessorTest and will see that P will be resolved to Processor, but it won't modify AbstractProcessorTest as it's already compiled. Still it will take into account P everywhere possible in ProcessorTest, so its bytecode may contain possible cast opcodes.
- When you run it, the current Mockito code charged to instantiate mocks based on fields will see for field
P processor the type AbstractProcessor not the type Processor that you fixed in ProcessorTest. Of course it will create the mock accordingly.
- The CCE is raised in the
ProcessorTest.setUp method because the compiler certainly introduced a silent cast opcode due to the generic nature of the field processor.
Also it looks reaaaally weird to configure mocks to call real method, it can lead to many issues, as mocks are not initialized with state. Maybe you want to use a spy instead ?
Hope that helps.
Previous answer that wasn't actually answering the real issue. But might still prove helpful with Mockito deep stubs
Yes Mockito in the current released version (1.9.5) doesn't support generics with deep stub (see issue 230), because Java implements generics with type erasure. So you it will only find the superior bound, be it Object or some other type that is known after erasure.
Generics are more of a compiler stuff than a runtime stuff. Search
google about why java people would like reified generics for a long long
time. Neal Gafter wrote about it in 2006
http://gafter.blogspot.fr/2006/11/reified-generics-for-java.html, but
there is other interesting reads out there.
EDITED vvvvvvvv 2015-01
However the compiler embeds some data about generics in some specific cases, in your example with this class declaration public class ProcessorTest extends AbstractProcessorTest<Processor, ProcessAlpha> it is possible to read both types. using the clunky and slow reflection API. The code exists in the master of Mockito code and should work in your example, but it is still unreleased due to other issues.
Since Mockito 1.10.x Mockito is way more aware of generics, i.e. if the mocked type like this declaration embeds types or boundaries it will use them, if a method has boundaries it will use them.
That means that code like that will work without additional stubbing, i.e mockito will discover boundaries embedded in bytecode and mock them if possible (not final nor primitive) :
interface UberList<U> extends List<U extends Uber> {
U firstUber();
<D extends Driver> D driver();
}
uberList = mock(UberList.class, RETURNS_DEEP_STUB);
Uber u1 = uberList.iterator().next();
Uber u1 = uberList.firstUber();
Driver d = uberList.driver();
EDITED ^^^^^^^^
Of course runtime declaration still cannot be discovered. For example in List<Processor> pList; the Processor generic type info will be erased. The only available info that will be the one that compiler found while compiling List. Without displaying too much details on how it's done, that type information will be resolved to Object as the generic type information E upper bound will be resoled to Object by the compiler (it's an implicit upper bound, just as you don't have to write extends Object).
So, in the mean time you could either cast to the wanted type, simply don't use the deep stubs answer, or if you are adventurous you can compile yourself an unreleased version of Mockito with the updated deep stub answer.
Hope that helps.