-
Notifications
You must be signed in to change notification settings - Fork 22
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
Add Activity and Fragment Examples #22
Comments
Hi, what special problems are you facing when testing activities and fragments with Android Unit Tests/PowerMock/UnMock ? In general you can create an instance of the class under test in your test code and call the appropriate callbacks before calling the code you want to test. The difficult thing is to mock everything that is needed to fully run the code but that very much depends on your actual code. Bjoern |
@bjoernQ Thanks for the quick reply. How could I easily convert this dummy test https://github.com/jaredsburrows/android-gradle-java-app-template/blob/master/src/test/java/burrows/apps/example/template/activity/MainActivityTest.java#L19? This example uses How can we instrument the activity? |
I'll have a look into that. Just to double check: the objective is to get rid of Robolectric and just use Android's plain Unit Test + PowerMock(ito) + UnMock plugin? We did the same with a closed source project successfully before. |
@bjoernQ Exactly. I love Robolectric but sometimes memory usage and missing shadows can cause issues in the unit tests. It would be nice just to unit test against the real android jar. I like using Mockito vs PowerMock. Also, can your post a snippet of an Activity test from that closed source project? |
I had a look into the MainActivityTest. Since I am used to PowerMock(ito) I used that to mock things - seems you prefer the EasyMock API - but this should show the basic idea @RunWith(PowerMockRunner.class)
@PrepareForTest(MainActivity.class)
public class MainActivityTest {
@Test
public void testNotNull() throws Exception {
PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(AppCompatActivity.class));
MainActivity mainActivity = spy(new MainActivity());
FragmentManager mockFragmentManager = mock(FragmentManager.class);
when(mainActivity.getSupportFragmentManager()).thenReturn(mockFragmentManager);
FragmentTransaction mockTransaction = mock(FragmentTransaction.class);
when(mockFragmentManager.beginTransaction()).thenReturn(mockTransaction);
when(mockTransaction.add(anyInt(), any(Fragment.class))).thenReturn(mockTransaction);
mainActivity.onCreate(null);
Whitebox.invokeMethod(mainActivity, "onStart");
Whitebox.invokeMethod(mainActivity, "onResume");
Whitebox.invokeMethod(mainActivity, "onPause");
Whitebox.invokeMethod(mainActivity, "onDestroy");
assertThat(mainActivity, not(nullValue()));
}
.... For this to work you also need to set some test options testOptions {
unitTests.returnDefaultValues = true
} For this simple scenario you don't even need the UnMock plugin. It's just Android's Unit Test + PowerMock(ito). The test is still missing the verification code to make sure the fragment has been added (or not if the passed bundle is non-null). But I hope it sketches the general idea. A lot more setup is needed without Robolectric but I personally prefer it this way. ( While I am really impressed by all the work done by the Robolectric devs - it's just a very different approach) |
@bjoernQ Thanks for the example! Why do you have to mock anything if we are using the Are you mocking as a way just to invoke the methods via Also, why use?
|
UnMock basically copies the original classes into the classpath (besides doing some class file transformation magic). That works for a lot of classes - e.g. TextUtils, SparseArray ..... It doesn't work for framework classes that rely on a lot of Android internals. That's the main difference to Robolectric - Robolectric tries to emulate Android. The idea with UnMock is that you have much more control over what is mocked and how. Which needs quite a lot of setup compared to Robolectric. It works best in an architecture where application logic is more decoupled from the Android framework while not trying to abstract everything that Android offers. (e.g. I prefer the PresentationModel ( http://martinfowler.com/eaaDev/PresentationModel.html ) for abstracting presentation logic which works like a charm also for testing and IMHO suits Android very well). IMHO it's much easier to start with Robolectric but my decision to not use it was
So just taking the real implementations of Activity / FragmentManager won't work in a desktop JVM environment. Making it all work out of the box would result in a rebuild of Robolectric from scratch. But in a real project we use helper classes which setup proper / suitable mocking for all these things and the tests don't contain all the mock setup boiler plate code. The testOption is just there to not have to mock really everything. i.e. it makes the stubs return null/zero instead of throwing a "StubException". I was thinking of a "best practice" example project explaining all these things but unfortunately haven't had the time yet. ( And finding an example that is not too complex but complex enough is the hardest part of it for me ) Hope this helps and makes it more clear what UnMock is and what it not is (and never should be). |
@bjoernQ Once again, thank you for your explanation! Maybe we can start with more pull requests to add more examples? |
@bjoernQ There are still no examples here: https://github.com/bjoernQ/unmock-plugin/tree/master/example/src/test/java/de/mobilej/testproject. I believe with an |
No description provided.
The text was updated successfully, but these errors were encountered: