【发布时间】:2017-03-02 14:36:44
【问题描述】:
我按照这里的说明进行操作:
- https://github.com/robolectric/robolectric/wiki/Using-PowerMock
- https://github.com/realm/realm-java/tree/master/examples/unitTestExample
设置我的领域单元测试。测试全部通过,但是当我尝试生成代码覆盖率以推送到 SonarQube 时,覆盖率报告显示 0% 的覆盖率。当我执行标准的 Android Studio 代码覆盖率时(如此处的答案所述:How to get code coverage using Android Studio?),它会生成一个显示 91% 覆盖率的报告。然而,这种方法的问题在于它是一个 html 报告,无法让它生成可用于 SonarQube 的 xml 报告。
这是测试类的代码
@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's 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();
}
}
我认为问题出在以下行:
@Rule
public PowerMockRule rule = new PowerMockRule();
但是,如果我删除此行,尽管 @PrepareForTest 行未更改,但我会收到以下错误。:
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.
【问题讨论】:
-
我完全放弃 Powermock 的原因之一就是:有时,有些东西根本不起作用。你花了 小时 研究它;大多数情况下没有找到任何解决方案。
-
你能分享你的课程资源吗?
标签: unit-testing realm code-coverage robolectric powermock