Open bacecek opened 2 months ago
@bacecek It's not recommended using mock with Robolectric together. You can only use mock for one test file, for example mocking Activity, Context by yourself. You can only use Robolectric for your one test file by leveraging Robolectric's fake implementations of Android Frameworks. But it's not allowed/recommended to use them together as they use similar mechanism to modify class not and generate extra code for mocking purpose or shadow purpose, and sometimes they have conflicted with each other.
cc @charlesmunger
It is generally OK to mock Android objects, but there are a certain set of them that I would not recommend mocking. They are banned from being mocked internally at Google. These are the very large, complex classes like Context, Fragment, Resources, View, Activity, Application, etc..
Let's take Context for example. It's a very very complex class with hundreds of methods, many of which are @hide
API, so these hidden methods are only invoked by other classes in the Android framework.
There are a lot of Android classes that take Context as a parameter. One I dealt with today was ViewConfiguration.get(Context), which builds a ViewConfiguration given the Context.
Let's say you are using a mock Context when calling ViewConfiguration.get(Context). You would have to implement:
@hide
methodNow let's say that the new Version of Android introduced some new properties in ViewConfiguration, and some of those are derived from other methods in Context. You will now have to update the Context mock to try to return sensible values for those.
So you will typically feel the pain when you update the SDK level used in Robolectric tests.
Perhaps for a small development team this would not be a large burden. But at scale, for a company like Google, multiply these issues by hundreds of apps and thousands of developers, and updating the Android SDK becomes a very large challenge.
If people standardize on using Context objects built in Robolectric, there is a single place that needs to be changed if there are incompatibilities.
I found the following recommendation in various issues about using mocking frameworks for mocking Android classes like Activity/Context/etc.:
Unfortunatelly, I've not found this recommendation in Android open source projects: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:docs/testing.md https://cs.android.com/android/platform/superproject/main or this robolectric repo.
Moreover, when any Android related class is used in test without Robolectric runner, the following exception fails the test:
which points to the page https://developer.android.com/training/testing/local-tests#mocking-dependencies, where example shows that mocking
Context
is okay.Could someone explain why mocking Android classes is the a bad idea and why?