2016-10-20 5 views
5

Я следовал инструкциям:Realm с Robolectric и PowerMock генерации покрытия кода нулевой%

настроить свои тесты Realm единицы. Все тесты проходят, но когда я пытаюсь создать покрытие кода, чтобы нажать на SonarQube, отчет о покрытии показывает 0% покрытия. Когда я выполняю стандартное покрытие кода Android Studio (как описано в ответе здесь: How to get code coverage using Android Studio?), он генерирует отчет, который показывает охват 91%. Однако проблема с этим подходом заключается в том, что это html-отчет, и нет возможности дать ему отчет xml, который можно использовать для SonarQube.

Это код тестового класса

@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. 
+1

Одна из причин, по которой я полностью отказался от Powermock, заключается в том, что: иногда что-то просто не работает. И вы потратили ** часы ** на изучение; чаще всего не найдя для этого никакого решения. – GhostCat

+0

Можете ли вы поделиться своим источником? –

ответ

2

Я думаю, вы используете Jacoco для сбора покрытия. И PowerMock имеет известный issue с Jacoco/EclEmma. Мы исправим его в следующем выпуске.

Обновление: PowerMock 1.6.6 был выпущен. Он включает исправление для скрытого инструментального кода JaCoCo. Итак, теперь вы можете получить покрытие кода с помощью плагина JaCoCo maven и offline instrumentation

+0

Я пробовал с Jacoco и Cobertura, оба дают 0%. Любая идея, когда придет следующий релиз? –

+0

Надеюсь, мы выпустим новую версию в середине ноября. –

+0

@LenGoyvaerts выпущена новая версия. Он включает исправление для скрытого инструментального кода JaCoCo. –

Смежные вопросы