Mockito is generating your mock class at runtime. Mocks are created by subclassing a given class and by overriding all of its methods. (Thus the limitation of not mocking final classes or methods.) At runtime, all generic types are erased and replaced by their upper type bound, in your AbstractCarTest this is Object as you do not specify an explicit upper bound. Therefore, Mockito sees your raw class as:
public abstract class AbstractCarTest {
@Mock
protected Object carMock;
}
at runtime and will create a mock that extends Object instead of your desired Truck class. (You cannot see this because cglib has a bug where it cannot extend Object directly. Instead, Mockito is extending an internal class called ClassWithSuperclassToWorkAroundCglibBug.) Usually, the compiler would issue a type error at compile time where the generic type is still available but at runtime, you experience heap pollution instead.
A work around would be as follows:
public abstract class AbstractCarTest<T> {
protected abstract T getCarMock();
// define some base test cases here that use the generic type.
}
public class TruckTest extends AbstractCarTest<Truck> {
@Mock
private Truck carMock;
@Override
protected Truck getCarMock() { return carMock; }
// ...
when(truckFactory.getTruck(anyString()).return(getCarMock());
}
By defining your mocked type without using generics, you are able to access the mock from the abstract base class by a getter where the mocked type is correctly defined as Truck.