Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gson behaviour is different in Unit test and in actual build #2713

Open
The-Pascal opened this issue Jul 19, 2024 · 2 comments
Open

Gson behaviour is different in Unit test and in actual build #2713

The-Pascal opened this issue Jul 19, 2024 · 2 comments
Labels
bug kotlin Issues concerning the use of Gson with Kotlin needs-info

Comments

@The-Pascal
Copy link

The-Pascal commented Jul 19, 2024

Gson version

2.11.0

Java / Android version

JDK 17
Sample of my build.gradle

android {
    namespace = "com.test.package"
    compileSdk = Config.compileSdk

    defaultConfig {
        minSdk = Config.minSdk
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    compileOptions {
        sourceCompatibility = Config.sourceCompatibility
        targetCompatibility = Config.targetCompatibility
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}

dependencies {
    testImplementation("junit:junit:4.13.2")
    testImplementation("androidx.test:core:1.6.1")

    implementation("com.google.code.gson:gson:2.11.0")
}

Description

While using Gson in unit tests, when converting json string to data class, if json string doesn't contains some fields, then it falls to default of data type like for nullables it falls to null.
However, on actual builds, it's taking default values when json string doesn't contains some fields.

Expected behavior

Both actual app behaviour and unit tests behaviour for Gson should be same.

Actual behavior

In actual app if fields are missing, then it takes data class default values.
In unit tests, if fields are missing, then it takes data type default (like for int - 0, for nullables - null, etc)

Reproduction steps

Run this unit test using android studio.

class JsonConverterTest {

    data class Person(
        val name: String,
        val age: Int,
        val isVerified: Boolean = false,
        val margin: Float = 1.0f,
        val gains: Double = 2.0,
        val profit: Double? = 4.0,
        val friends: List<String>? = listOf()
    )

    @Test
    fun `test gson serialization`() {
        val jsonString = """{"name":"John","age":30,"isVerified":true,"margin":1.0,"gains":5.0}"""
        val actual = Gson().fromJson(jsonString, Person::class.java)

        val expected = Person("John", 30, true, 1.0f, 5.0, 4.0, listOf())

        assertWithMessage("Failed for case: $jsonString").that(actual).isEqualTo(expected)
    }
}

Output after running above unit test

Failed for case: {"name":"John","age":30,"isVerified":true,"margin":1.0,"gains":5.0}
expected: Person(name=John, age=30, isVerified=true, margin=1.0, gains=5.0, profit=4.0, friends=[])
but was : Person(name=John, age=30, isVerified=true, margin=1.0, gains=5.0, profit=null, friends=null)

Expected output

Test should get passed.

PS: let me know if I missed something

@The-Pascal The-Pascal added the bug label Jul 19, 2024
@Marcono1234 Marcono1234 added the kotlin Issues concerning the use of Gson with Kotlin label Jul 19, 2024
@Marcono1234
Copy link
Collaborator

Marcono1234 commented Jul 19, 2024

The behavior of the unit test is likely caused by Gson's limited support for Kotlin (see also the Gson README and #2666). Gson does not consider default values for constructor and function arguments, and because your class does not have a no-args constructor, Gson will fall back to using Unsafe to create the instance, which does not invoke any constructor. If you use GsonBuilder.disableJdkUnsafe(), it will probably fail, indicating that it previously relied on Unsafe.

Not sure why it works as expected in release mode. Maybe the code shrinker R8 is rewriting the code in a way which causes the class to have a no-args constructor. Out of curiosity, if you disable R8, does the release build then behave in the same (unexpected) way as the unit test?

We already have other GitHub issues for not well supported Kotlin features, see the kotlin Issues concerning the use of Gson with Kotlin label and particularly #1657. So this issue here is probably a duplicate.

@The-Pascal
Copy link
Author

Thanks for quick reply @Marcono1234
I will check with disabling R8, if the release build behaves the same then

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug kotlin Issues concerning the use of Gson with Kotlin needs-info
Projects
None yet
Development

No branches or pull requests

2 participants