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?
To prevent the ClassCastException exception, one should be careful when casting objects to a specific class or interface and ensure that the target type is a child of the source type, and that the actual object is an instance of that type.
Introduction. ClassCastException is a runtime exception raised in Java when we try to improperly cast a class from one type to another. It's thrown to indicate that the code has attempted to cast an object to a related class, but of which it is not an instance.
initMocks(this); initializes fields annotated with Mockito annotations. Allows shorthand creation of objects required for testing. Minimizes repetitive mock creation code. Makes the test class more readable.
Your mock object is enhanced by Mockito and it is not same as your class, so you can't type cast. Thanks for contributing an answer to Stack Overflow!
Because if you start googling around for "Mockito cannot mock this class CrudRepository" you'll hit a lot of articles about how Spring Boot (particularly in regards to the @WebMvcTest annotation) creates the application context and when beans are available and what name they have when they're made available and all that.
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.
because interface is an abstract. You can do an anonymous class implementing this interface: and then you'll be able to cast but you can get exception: ClassCastException if the class is not implementing mentioned interface. because you already have instance created.
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
.
Mockito can deal with mocked objects that are alread 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; // chaged 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With