Hot questions for Using Mockito in classcastexception

Top 10 Java Open Source / Mockito / classcastexception

Question:

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?


Answer:

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.

Question:

I have the following method for which I'm trying to write unit test using Mockito. I'm fairly new to Mockito and trying to catch up.

Method to test
public synchronized String executeReadRequest(String url) throws Exception{

    String result = null;
    RestClient client = null;
    Resource res = null;
    logger.debug("Start executing GET request on "+url);

    try{
         client = getClient();
         res = client.resource(url);
         result = res.contentType(this.requestType).accept(this.responseType).get(String.class);
    }
    catch(Exception ioe){
        throw new Exception(ioe.getMessage());
    }
    finally{
        res = null;
        client = null;
    }

    logger.info("GET request execution is over with result : "+result);
    return result;
}

The unit test with Mockito

@Test
public void testRestHandler() throws Exception {
    RestHandler handler = spy(new RestHandler());
    RestClient mockClient = Mockito.mock(RestClient.class,Mockito.RETURNS_DEEP_STUBS); 
    Resource mockResource = Mockito.mock(Resource.class,Mockito.RETURNS_DEEP_STUBS);

    doReturn(mockClient).when(handler).getClient();
    Mockito.when(mockClient.resource(Mockito.anyString())).thenReturn(mockResource);

  //ClassCastException at the below line
    Mockito.when(mockResource.contentType(Mockito.anyString()).accept(Mockito.anyString()).get(Mockito.eq(String.class))).thenReturn("dummy read result");

    handler.setRequestType(MediaType.APPLICATION_FORM_URLENCODED);
    handler.setResponseType(MediaType.APPLICATION_JSON);
    handler.executeReadRequest("abc");
}

But I'm getting a ClassCastException at the line

Mockito.when(mockResource.contentType(Mockito.anyString()).accept(Mockito.anyString()).get(Mockito.eq(String.class))).thenReturn("dummy read result");

Exception

java.lang.ClassCastException: org.mockito.internal.creation.jmock.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$EnhancerByMockitoWithCGLIB$$4b441c4d cannot be cast to java.lang.String

Appreciate any help to resolve this.

Many thanks.


Answer:

This style of chaining during stubbing isn't correct:

Mockito.when(
    mockResource.contentType(Mockito.anyString())
        .accept(Mockito.anyString())
        .get(Mockito.eq(String.class)))
    .thenReturn("dummy read result");

Even though you've set the mocks to return deep stubs, Matchers work via side-effects, so this line doesn't achieve what you think it does. All three matchers (anyString, anyString, eq) are evaluated during the call to when, and the way you have it your code is likely to throw InvalidUseOfMatchersException at the slightest provocation—including adding unrelated code or verifications later.

This means your problem isn't the use of eq(String.class): It's that Mockito is trying to work the Class matcher in where it doesn't belong.

Instead, you'll need to stub specifically:

Mockito.when(mockResource.contentType(Mockito.anyString()))
    .thenReturn(mockResource);
Mockito.when(mockResource.accept(Mockito.anyString()))
    .thenReturn(mockResource);
Mockito.when(mockResource.get(Mockito.eq(String.class))) // or any(Class.class)
    .thenReturn("dummy read response");

Note that some of the difficulty here is that Apache Wink uses the Builder pattern, which can be laborious in Mockito. (I've returned mockResource here, but you could imagine returning specific other Resource objects, at the expense of requiring them in exactly that order later.) A better way might be to use a default Answer that returns this whenever possible.

Question:

I'm rather new to java and I'm wondering if someone could point me in the correct direction. I'm trying to mock (using mockito) a method that has the following code:

Channel channel = session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
channel.setInputStream(null);

I get a ClassCastException on the line:

((ChannelExec)channel).setCommand(command);

The exception is as follows:

java.lang.ClassCastException: com.jcraft.jsch.Channel$$EnhancerByMockitoWithCGLIB$$15aeab7e cannot be cast to com.jcraft.jsch.ChannelExec

Here is my unit test:

    @Test
public void testExecuteSSHCommand() throws JSchException, IOException {
    Channel channel = mock(Channel.class);
    ChannelExec channelExec = mock(ChannelExec.class);

    String command = "dummyCommand";
    String result = "the correct result";
    InputStream inputStream = new ByteArrayInputStream(result.getBytes(StandardCharsets.UTF_8));;

    when(channel.getInputStream()).thenReturn(inputStream);
    when(session.openChannel("exec")).thenReturn(channel);
    //when(channel.setCommand(command)).get();

    logger.info("Returning {}", sshClient.executeSSHCommand(session, command));
    assertEquals(result, sshClient.executeSSHCommand(session, command));
}

Channel is an abstract class and ChannelExec is a pojo


Answer:

If you want openChannel to return a ChannelExec

 Channel channel = session.openChannel("exec");
 ((ChannelExec)channel).setCommand(command);

you need to specify that

when(session.openChannel("exec")).thenReturn(channelExec);

Question:

I am in a situation where I need to Mock two static methods using PowerMocklito. It gives me a mocked object for the first line of code but then the same method is called again but this time it is returning a different object and this throws ClassCastException.

Method Under test

ESignatureJaxBContextFactory context = (ESignatureJaxBContextFactory) AppContext.getBean("jaxbContextFactory");
/// More code
DocusignRESTClient client = (DocusignRESTClient) AppContext.getBean("restServiceClient");

Junit

private ESignatureJaxBContextFactory eSignatureJaxBContextFactory;
eSignatureJaxBContextFactory = mock( ESignatureJaxBContextFactory.class );

PowerMockito.when( AppContext.getBean( any( String.class ) ) ).thenReturn( eSignatureJaxBContextFactory );

So above line of code returns me mock context, but I get an exception when it tries to fetch client. How can I test this?

Thanks in advance


Answer:

The problem is that you are mocking AppContext.getBean for any( String.class ) Try this:

PowerMockito.when(AppContext.getBean("jaxbContextFactory"))
            .thenReturn(eSignatureJaxBContextFactory);
PowerMockito.when(AppContext.getBean("restServiceClient"))
            .thenReturn(docusignRESTClient);

In this case when AppContext.getBean is invoked with parameter "jaxbContextFactory" it will return eSignatureJaxBContextFactory but not for any other parameters. So you also need to mock invocation with parameter "restServiceClient".

Other way of testing it is to provide a set of consecutive return values:

PowerMockito.when(AppContext.getBean(any(String.class)))
            .thenReturn(eSignatureJaxBContextFactory, docusignRESTClient);

In this case you still mock any invocation of AppContext.getBean with any String value as parameter, but are telling mockito to return eSignatureJaxBContextFactory on first invocation and to return docusignRESTClient on second and any further invocations.

Question:

I am trying to write Junit tests for a Controller class which contains the following method.

 @RequestMapping(value = "/mappingUrl", method = RequestMethod.POST)
public String uploadFileMethod(HttpServletResponse httpResponse, HttpServletRequest httpRequest, ModelMap model) throws Exception {

  try {
    MultipartFile multipartFile = ((MultipartHttpServletRequest) httpRequest).getFile("fileName");
   }
  catch(Exception e){}
}

In the test class I have the following method

 @Test
public void testUploadFileMethod() throws Exception {
mockMVC.perform(post("/mappingUrl")).andExpect(status().isOk());
}

I am getting the the below exception when the test is executed:

java.lang.ClassCastException: org.springframework.mock.web.MockHttpServletRequest cannot be cast to org.springframework.web.multipart.MultipartHttpServletRequest

Is there a way I can test the method without changing the existing code? The class is used through out the application and I am afraid I might break something else.

I went through questions that were similar and the following are the ones that came close:

Mockito ClassCastException - A mock cannot be cast

pass remoteUser value in HttpServletRequest to mockmvc perform test


Answer:

Just try

MockMultipartFile myFile = new MockMultipartFile("data", "myFile.txt", "text/plain", "myFileContent".getBytes());
mockMVC.perform(MockMvcRequestBuilders.multipart("/mappingUrl")
                    .file(myFile)).andExpect(status().isOk());

as explained here