我可以在 PowerMock 的单元测试中使用 Cobertura 吗?

Posted

技术标签:

【中文标题】我可以在 PowerMock 的单元测试中使用 Cobertura 吗?【英文标题】:Can I use Cobertura on Unit Tests with PowerMock? 【发布时间】:2016-07-17 01:21:34 【问题描述】:

问题

我正在为一个 android 库设置单元测试代码覆盖率,该库使用 Robolectric 运行测试并使用 PowerMock/Mockito 进行模拟测试。

但是,使用 Cobertura 运行单元测试会导致以下异常...

:example:testDebugUnitTest
Exception in thread "Thread-5" java.lang.ExceptionInInitializerError
    at com.example.package.saas.Query$RemoveWordsType.__cobertura_init(Query.java)
    at com.example.package.saas.Query$RemoveWordsType.<clinit>(Query.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at net.sourceforge.cobertura.coveragedata.TouchCollector.applyTouchesToSingleClassOnProjectData(TouchCollector.java:123)
    at net.sourceforge.cobertura.coveragedata.TouchCollector.applyTouchesOnProjectData(TouchCollector.java:110)
    at net.sourceforge.cobertura.coveragedata.ProjectData.saveGlobalProjectData(ProjectData.java:272)
    at net.sourceforge.cobertura.coveragedata.SaveTimer.run(SaveTimer.java:33)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Shutdown in progress
    at java.lang.ApplicationShutdownHooks.add(ApplicationShutdownHooks.java:66)
    at java.lang.Runtime.addShutdownHook(Runtime.java:211)
    at net.sourceforge.cobertura.coveragedata.ProjectData.initialize(ProjectData.java:239)
    at net.sourceforge.cobertura.coveragedata.ProjectData.getGlobalProjectData(ProjectData.java:209)
    at net.sourceforge.cobertura.coveragedata.TouchCollector.<clinit>(TouchCollector.java:45)
    ... 11 more

...生成的 Cobertura 报告根本没有显示任何覆盖范围。


在没有 PowerMock* 的情况下运行相同的测试用例,测试运行良好,覆盖率报告生成成功:

​* 即使用 PowerMock 注释测试,删除 PowerMockIgnore 注释、PowerMockRuleMockitoAnnotations.initMocks(this); 调用。


调查

我看到一些用户 fixed a similar issue 通过在他们的测试套件中设置 forkmode="once"。 但是,这不是解决方案,因为我使用 Gradle which defaults on Java projects 到 ForkMode.ONCE。 其他用户报告了类似问题fixed it by updating PowerMock to 1.5.4。 我尝试降级到此版本,但问题仍然存在。 最后,explicitly specifying a dependency to cobertura-runtime 修复了一个类似的问题,但添加它也没有改变任何东西。

问题

是否可以将 CoberturaPowerMock 结合使用?

那么,我错过了什么? 否则,我应该如何使用这样的设置测量代码覆盖率(Android Library + Robolectric + PowerMock)?

【问题讨论】:

我遇到了同样的问题。 Gradle 构建,Powermock 测试以 0% 的覆盖率显示。很想解决这个问题。 +1 对于您非常明确的问题。您能否分享一个重现该问题的基本项目(例如在 github 上)? 在您的测试用例中,您是否从 PowerMockTestCase 扩展类? @gontard:我可以这样做,但是从当前项目中提取相关部分需要一些时间。它会帮助您解决此问题吗?如果这是您希望看到的,我还可以创建构建脚本和测试用例的要点。 @MoralesBatovski:不是真的,因为我遵循 robolectric 的指示 (github.com/robolectric/robolectric/wiki/Using-PowerMock)。你会建议另一种方法吗? 【参考方案1】:

目前,Android Studio 自动集成了 jacoco 来进行代码覆盖。

你只需要添加几行代码:


apply plugin: 'jacoco-android'

android 
   buildTypes 
      debug 
         testCoverageEnabled = true
      
   

更多信息在这里:

http://blog.wittchen.biz.pl/test-coverage-report-for-android-application/

【讨论】:

我尝试了您的解决方案,但添加 jacoco 并运行 createDebugCoverageReport 会生成 [空报告](i.stack.imgur.com/ACTcY.png)。除此之外,您确定 jacoco 适用于单元测试 (test) 而不仅仅是仪器测试 (androidTest)?您链接的文章是后者,而我正在尝试使用 Robolectric 实现前者。

以上是关于我可以在 PowerMock 的单元测试中使用 Cobertura 吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Powermock 在 Sonarqube 中配置 jacoco 以进行集成和单元测试报告

配置同时使用PowerMock和Robolectric对Android进行单元测试

配置同时使用PowerMock和Robolectric对Android进行单元测试

基于Junit5+PowerMock的单元测试框架

关于单元测试,其实你也可以这样来写

PowerMock单元测试