10

I'm trying to cover as much as possible a Kotlin Android library and I'm encountering an issue about custom BuildConfig variable, better known as buildConfigField.

I would like to mock this variable to test both true and false values.

Extract from Gradle file :

android {
    defaultConfig {
        buildConfigField "boolean", "ENABLE_LOG", "false"
    }
    flavorDimensions "log"
    productFlavors {
        loggable {
            buildConfigField "boolean", "ENABLE_LOG", "true"
            dimension "log"
        }
        notloggable {
            dimension "log"
        }
    }
}

Extract of the Kotlin function to be tested :

fun buildClient(): MyClient {
    var myClientBuilder : MyClient.Builder = MyClient.Builder();

    if (BuildConfig.ENABLE_LOG) {
        val interceptor = LoggingInterceptor();
        interceptor.setLevel(LoggingInterceptor.Level.ALL);
        myClientBuilder.addInterceptor(interceptor);
    }

    return myClientBuilder.build()
}

Unit test :

@Test
fun buildClient_enableLog_oneInterceptor() {
    // GIVEN
    Mockito.mock(BuildConfig::class.java)
    Mockito.doReturn(true).`when`(BuildConfig.ENABLE_LOG)

    // WHEN
    val myClient = myService!!.buildClient()

    // THEN
    assertNotNull(myClient)
    assertNotNull(myClient.interceptors())
    assertEquals(1, myClient.interceptors().size)
}

I tried different things and it never works. If someone have already done this work, it can help me a lot (and others I guess).

Thanks

BapNesS
  • 183
  • 3
  • 10
  • 6
    Why don't you send the variable `BuildConfig.ENABLE_LOG` as an argument to your function? That way you can mock it for testing by calling `buildClient(enableLog: Boolean)` ? Or pull it to the class level by sending it in the constuctor of the class containing the function? OR use dependency injection to inject the variable into your class? – Usama K. Zafar Sep 05 '18 at 10:38
  • I found a solution in the documentation : https://developer.android.com/studio/test/ You can check code at : https://github.com/BapNesS/android-unittests-demo – BapNesS Sep 06 '18 at 12:24
  • @BaptisteCarlier Can you please write that as an answer with some details? It's hard to follow the link to your code as there are a lot of other classes there that might need to check for the answer to this specific question. Just a simple snippet should do the job I think. – Reaz Murshed Oct 09 '19 at 20:25
  • Plus both of his links not working Seems to a spam comment – AndroidEngineX Nov 21 '22 at 09:26

3 Answers3

5
ReflectionHelpers.setStaticField(BuildConfig::class.java, "ENABLE_LOG", true)
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Dev Soni
  • 489
  • 4
  • 12
0

By default, all tests run against the debug build type. You can change this to another build type by using the testBuildType property in your module-level build.gradle file. For example, if you want to run your tests against your "staging" build type, edit the file as shown in the following snippet.

android { ... testBuildType "staging" } but this is causing other options to fail

Sahil
  • 25
  • 7
0

Little late to the party but this is how you should test any thing related to BuildConfig file. BuildConfig.java is generated for each variant of your app. In your case you have atleast 4 variants.

  1. LoggableDebug
  2. LoggableRelease
  3. NotloggableDebug
  4. NotloggableRelease

ENABLE_LOG will be false for options 3 and 4. If you want to Unit test this, I recommend writing UnitTest in src/testNotLoggable/java/com/.../TestFile.java.

In that TestFile.java your BuildConfig.ENABLE_LOG should be false.

You can check BuildConfig.java file for each variant under /build/source/buildConfig/flavorname/debug/com/project/../BuildConfig.java

Prakash
  • 7,794
  • 4
  • 48
  • 44