I recently wrote a simple java app with Dagger 2 as a DI container and Gradle as a build system. I wanted to generate unit test coverage report for this app, so I used Jacoco.

In my build.gradle file I configured JaCoCo as follows:

plugins {
  id 'jacoco'
}

jacocoTestReport {
  reports {
    xml.enabled = true
    html.enabled = true
  }
}

Now, I could type:

./gradlew test jacocoTestReport

Report was generated in build/reports/jacoco/ directory. I noticed that report includes Java code generated by Dagger during the compilation. I didn’t want to include it in the report because it doesn’t really make any sense to write unit tests for generated code.

I compiled project and browsed classes generated in build/classes/ directory. I’ve noticed that Dagger classes have similar patterns like:

  • DaggerApplicationComponent.class
  • ControllerModule_MemberInjector.class
  • ControllerModule_ProvideContextWrapperFactory.class
  • AccountController_Factory.class
  • and so on…

As you can see ApplicationComponent interface got its implementation with Dagger prefix and classes related to modules has postfixes like _MemberInjector, _Provide* and _Factory.

With this knowledge, I could improve my JaCoCo configuration and exclude classes, which match the Dagger pattern.

jacocoTestReport {
  reports {
    xml.enabled = true
    html.enabled = true
  }

  afterEvaluate {
    classDirectories = files(classDirectories.files.collect {
      fileTree(dir: it,
              excludes: [
                      '**/*_Provide*/**',
                      '**/*_Factory*/**',
                      '**/*_MembersInjector.class',
                      '**/*Dagger*'
              ])
    })
  }
}

Now, my report contains only code which was written by me and automatically generated classes are excluded.

You can apply similar trick while using other libraries, which generates Java code.