Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.ClassCastException: java.lang.Class cannot be cast to {Mock method return type} #717

Open
fdz-nelson-branco opened this issue Dec 21, 2021 · 5 comments

Comments

@fdz-nelson-branco
Copy link

Please provide the following information:

  • Version of JMockit that was used: 1.35 and 1.49

  • Description of the problem or enhancement request: from time to time, we get a "java.lang.ClassCastException: java.lang.Class cannot be cast to {Mock method return type}" on either a local variable initialization or a method call argument.
    I couldn't yet determine a specific deterministic use case.

@Saljack
Copy link

Saljack commented Dec 22, 2021

Do you have a code example? What do you use MockUp or @Injectable etc?

@fdz-nelson-branco
Copy link
Author

I'm in an effort of fixing this flaky symptom over a couple of tests. It happens on Mocked and Injectable references, much more frequent on Injectables, I've a couple of comments on the code stating that they had mocked it using Mockups due to issues using Expectations but with no further details.

One of the cases we can put it like this:

public void someTestMoethod(@Mocked final Dependency1 dependency1) {
    final long id = dependency1.getId(); // <<--- rarely it throws "java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.Long"
}

It occurs both with or without an expectation.
The machine has it's CPU exhausted running the test in parallel, process forked per class, and executing sequentially over the class.

I'm looking into the source code trying to make sense of it.
I spotted this exception (on a passing test) on a scheduled task that continues after the test case, this I think to be related to the mocking being "cleanup" upon the test case finishes.
Also, as far as I understood, since the mocking structures aren't synchronized, we must not create expectations using multiple threads, at least without the proper synchronization.

Even so, I still can make sense of it on the case shown above.

Much appreciated your help, even if you can only guide me on where to look for on the code.

@fdz-nelson-branco
Copy link
Author

Narrowing down a little bit more with additional details:

interface Dependency1Interface {
    Identifier getId();
}

class Dependency1 implements Dependency1Interface {}

public void someTestMethod(@Mocked final Dependency1 dependency1) {
    final Identifier id = dependency1.getId(); // <<--- rarely it throws "java.lang.ClassCastException: java.lang.Class cannot be cast to com.foo.Identifier"
}

So far I managed to reverse engineer the getId() redefined method into the following:

public getId()Ljava/foo/Identifier;
    ALOAD 0
    LDC 1025
    LDC "com/foo/Dependency1Interface"
    LDC "getId()Lcom/foo/Identifier;"
    ACONST_NULL
    LDC 0
    ACONST_NULL
    INVOKESTATIC mockit/internal/expectations/RecordAndReplayExecution.recordOrReplay (Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I[Ljava/lang/Object;)Ljava/lang/Object;
    CHECKCAST com/foo/Identifier
    ARETURN
    MAXSTACK = 7
    MAXLOCALS = 1

Seems to me that this CHECKCAST com/foo/Identifier is the source of the exception.
If that's true, that mean the Class instance is being returned by the RecordAndReplayExecution.recordOrReplay.

@fdz-nelson-branco
Copy link
Author

Adding up on the findings...

I spotted that within certain circumstances, like the case where a task continues to run after the end of the test case, the RecordAndReplayExecution.recordOrReplay returns Void.class, so, this Void.class's must be on the root of the exception being thrown, now, on the getId() scenario I can't figure out why it fails from time to time...

@zbflcy
Copy link

zbflcy commented Jun 30, 2023

Why hasn't this problem been fixed yet?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants