Robolectric is not compatible with latest Mockito experimental feature for mocking finals:
I'm with Robolectric 3.1.2.
I'm also running into this issue. Tests run with the RobolectricTestRunner will fail whenever the mocking feature is enabled. If I switch the test runner to JUnit4 then I don't get any errors. I made a small test project to verify.
Robolectric and Mockito experimental feature both are using bytecode manipulation. Clear they might conflict. We had similar issues before when we tried to use Robolecric and PowerMockito. I wonder if it is possible to live them together. That would be great!
Agreed, especially when trying to mock Retrofit 2 since the Retrofit and Call objects are final. Since the final class mocking in Mockito 2 is still an incubating feature I think we will have to wait until it is fully ready before finding a cause of this issue.
If you are testing out Retrofit, I highly recommend using OKHttp's MockWebserver. It will at least let you make sure your mappings are correct and the input outputs are hitting the correct endpoints. Since both Mockito and Robolectric are doing byte code manipulation it may be a while before a solution is found that works with both.
@kingargyle, thanks! But we are talking about unit testing now.
@emartynov Yes I realize that. And Yes MockWebserver gets away from true unit testing, but in the case where you can't get around the mocking of the final classes, (you run into similar issues when writing tests for code that uses OkHttp), the mockwebserver allows you to at least test the results, and not incure the full overhead of a true Integration Test.
Also running into this issue.
Mockito maintainer here. I just debugged this and this turned out to be a combination of bugs in Mockito and Robolectrics.
Mockito throws an exception from the mock maker plugin's constructor upon an unexpected interaction with the Robolectrics class loader. This causes Mockito to attempt cleaning the stack trace what should not happen at this point as it is not a user fault but a configuration error. Cleaning stack traces runs via a plugin where the manager just failed loading the mock maker plugin what in turn results in a null pointer exception as the class initializer cannot correctly created the plugin manager where the class initializer was not executed to its end. I already fixed this in Mockito.
The mock maker does not work as the InstrumentingClassLoader does not correctly delegate to its parent after we inject a class into the bootstrap class loader. Instead of asking its parent class loader for org.mockito.internal.creation.bytebuddy.MockMethodDispatcher, the class loader loads the class in question directly from the class path and therefore voids the bootstrap injection. This results in the mock maker plugin not being able to instrument types globally where it cannot work as only the bootstrap loader is globally visible.
A correct class loader implementation must request a class from its parent first. In this case, I understand why this is not happening as the system class loaders class's should be shadowed. However, this should happen by super-seeding the class loader, not by some child-first mechanism. I implemented this as a proposal pull request. I did not get the tests of your project to work, unfortunately, there are dependencies missing and I am not familiar enough with the Android space to get this working quickly.
While investigating this, I found a second bug in the Robolectrics class loader where the standard class employment is broken when loading classes via Class::forName where ClassLoader::loadClass(String, boolean) is invoked, therefore surpassing your implementation. I did this for debugging purposes but I assume real libraries can also run into that.
Let me know if anything is unclear. Cheers.
@xian Any update on this bug? I'm still encountering it on mockito 2.6.2 and robolectric 3.2.2
We're working on this next week. :-)