'Mockito ClassCastException - A mock cannot be cast

I have a method in the class AppleProcessor which I would like to test:

public void process(Fruit fruit) {
    if(fruit.getType() == Fruit.APPLE) {
        fruitBasket.add(((AppleFruit) fruit).getApple());
    }
    else {
        // do something else
    }
}

Note that Fruit is an interface with the method getType() which AppleFruit implements and also has a getApple() method.

My test looks like:

@Mock
FruitBasket fruitBasket;

@Mock
Fruit fruit;

@Mock
AppleFruit apple;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testAnAppleIsProcessed() {
    AppleProcessor appleProcessor = new AppleProcessoer();
    when(fruit.getType()).thenReturn(Fruit.APPLE);
    when(((AppleFruit) fruit).getApple()).thenReturn(apple);

    appleProcessor.process(fruit);

    verify(fruitBasket).add(isA(Apple.class));
}

However I get the following error:

java.lang.ClassCastException: package.fruit.Fruit$$EnhancerByMockitoWithCGLIB$$b8254f54 cannot be cast to package.fruit.AppleFruit

which comes from this line in the test

when(((AppleFruit) fruit).getApple()).thenReturn(apple);

Would anyone know how to resolve this so I can test my code?



Solution 1:[1]

When you say

@Mock
Fruit fruit;

You tell Mockito: the fruit variable should be an instance of Fruit. Mockito will dynamically create a class which implements Fruit (this class is Fruit$$EnhancerByMockitoWithCGLIB$$b8254f54), and create an instance of this class. There's no reason for this class to be an instance of AppleFruit, since you didn't tell Mockito that the object had to be of type AppleFruit.

Declare it as AppleFruit, and it will be of type AppleFruit.

Solution 2:[2]

Mockito can deal with mocked objects that are already casted at mocking time (assignment). However, it does not cast by itself a mocked object during code execution.

In other words(or better yet, code):

Fruit fruit = Mockito.mock(Applefruit.class);

Just do as JB Nizet said and you will be fine. I had a similar problem and his solution worked.

For this question it would be:

@Mock
FruitBasket fruitBasket;

@Mock
AppleFruit fruit; // changed here

@Mock
AppleFruit apple;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testAnAppleIsProcessed() {
    AppleProcessor appleProcessor = new AppleProcessoer();
    when(fruit.getType()).thenReturn(Fruit.APPLE);
    when(((AppleFruit) fruit).getApple()).thenReturn(apple);

    appleProcessor.process(fruit);

    verify(fruitBasket).add(isA(Apple.class));
}

That is all what is needed.

Solution 3:[3]

You can instruct mockito to return an object of subclass type, for a method which returns a super-class object. Then you won't need to tell mockito to cast the object.

Solution 4:[4]

To anyone searching for this just include:

@Mock(extraInterfaces = {AppleFruit.class})
Fruit fruit;

Which will add an extra interface to the mock and the casting wont raise any exceptions.

Solution 5:[5]

Your mock object is enhanced by Mockito and it is not same as your class, so you can't type cast.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JB Nizet
Solution 2
Solution 3 Siba Prasad Tripathy
Solution 4 Markus Ridziauskas
Solution 5 Aninda Bhattacharyya