I followed the instructions below:
to set up my unit tests. All tests pass, but when I try to create code coverage to click on SonarQube, the coverage report shows 0% coverage. When I do standard coverage of Android Studio code (as described in the answer here: How to get code coverage using Android Studio? ), It creates a report that shows coverage of 91%, However, the problem with this approach is that it is html is a report and does not allow it to generate an xml report that can be used for SonarQube.
This is the test class code.
@RunWith(RobolectricTestRunner.class) @PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"}) @PrepareForTest({Realm.class, RealmConfiguration.class, RealmCore.class, RealmLog.class}) @SuppressStaticInitializationFor("io.realm.internal.Util") @Config(constants = BuildConfig.class, manifest = "src/main/AndroidManifest.xml", sdk = 21) public class DecisionTreeTest { @Captor ArgumentCaptor<Realm.Transaction.Callback> realmCallbackCaptor; // Robolectric, Using Power Mock https://github.com/robolectric/robolectric/wiki/Using-PowerMock @Rule public PowerMockRule rule = new PowerMockRule(); private Context mockContext; private final byte[] fakeRealmKey = { -122, -115, -113, -111, -105, -104, -101, -99, -94, -93, -90, -87, -77, -74, -67, -66, -63, -61, -56, -53, -48, -47, -33, -31, -30, -28, -22, -17, -5, -3, -1, 3, 8, 11, 17, 18, 21, 22, 27, 30, 40, 42, 51, 52, 53, 54, 57, 59, 61, 63, 67, 70, 74, 76, 78, 85, 90, 91, 103, 108, 113, 117, 119, 127 }; @Before public void setUp() throws Exception { // Setup Realm to be mocked. The order of these matters mockStatic(RealmCore.class); mockStatic(RealmLog.class); mockStatic(Realm.class); mockStatic(RealmConfiguration.class); this.mockContext = RuntimeEnvironment.application; Whitebox.setInternalState( Realm.class, "applicationContext", RuntimeEnvironment.application); /* Better solution would be just mock the RealmConfiguration.Builder class. But it seems there is some problems for powermock to mock it (static inner class). We just mock the RealmCore.loadLibrary(Context) which will be called by RealmConfiguration.Builder constructor. */ doNothing().when(RealmCore.class); RealmCore.loadLibrary(any(Context.class)); } @Test(expected = DecisionTreeException.class) public void persistSurvey_DecisionTreeRealmNotEnabled_ThrowsException() throws Exception { DecisionTree decisionTree = createSimpleDecisionTree(); Survey survey = decisionTree.getSurveyFromResource(R.raw.survey); decisionTree.persistSurvey(survey, null, null); } @Test(expected = DecisionTreeException.class) public void persistSurvey_NullAsFirstParam_ThrowsException() throws Exception { DecisionTree decisionTree = createRealmDecisionTree(); decisionTree.persistSurvey(null, null, null); } @Test public void persistSurvey_SurveyAsFirstParam_ThrowsException() throws Exception { final Realm mockRealm = mock(Realm.class); when(Realm.getInstance(any(RealmConfiguration.class))).thenReturn(mockRealm); org.mockito.stubbing.Answer<Void> executeAnswer = new org.mockito.stubbing.Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { ((Realm.Transaction) invocation.getArguments()[0]).execute(mockRealm); return null; } }; doAnswer(executeAnswer) .when(mockRealm) .executeTransactionAsync( any(Realm.Transaction.class), any(Realm.Transaction.OnSuccess.class), any(Realm.Transaction.OnError.class)); DecisionTree decisionTree = createRealmDecisionTree(); Survey survey = decisionTree.getSurveyFromResource(R.raw.survey); decisionTree.persistSurvey(survey, null, null); verify(mockRealm).executeTransactionAsync( any(Realm.Transaction.class), any(Realm.Transaction.OnSuccess.class), any(Realm.Transaction.OnError.class)); verify(mockRealm).copyToRealmOrUpdate(any(Survey.class)); } private DecisionTree createRealmDecisionTree() { return new DecisionTree.Builder() .setContext(mockContext) .setRealmKey(fakeRealmKey) .setRealmEnabled(true) .build(); } private DecisionTree createSimpleDecisionTree() { return new DecisionTree.Builder() .setContext(RuntimeEnvironment.application) .build(); } }
I think the problem is the following line:
@Rule public PowerMockRule rule = new PowerMockRule();
However, if I delete this line, I get the following error, although the @PrepareForTest line does not change .:
org.powermock.api.mockito.ClassNotPreparedException: The class io.realm.internal.RealmCore not prepared for test. To prepare this class, add class to the '@PrepareForTest' annotation. In case if you don't use this annotation, add the annotation on class or method level.