Unit test fails on JDK17 — What is the problem?

Recently, Android studio Flamingo 🦩 hit the stable channel. So I have updated the IDE and all works as expected.
Android studio Flamingo comes with default JDK set to
JDK17
- All works as expected until I run the unit tests for our project 💔
Our application support English and French. So we have unit tests for currency formatting to ensure it works as expected for both languages.
Tests for French currency formatted starts failing 😢 and we wonder why it starts falling on JDK17

From the failing tests, we found that there is an issue with the number separator
🤯.
For the French locale, the number separator is changed to a narrow no-break space(NNBSP) U+202F
It wasn’t changed in JDK
and it doesn’t just start with JDK17
Before JDK17
, We are using JDK11
. Until JDK12
there is no issue with the existing number separator(NBSP
)
So what changes the number separator for French
In this bug, I found that it was introduced by the change in Unicode Common Locale Data Repository(CLDR)
which is the upstream source of JDK
Fix
- If you are using a
hard-coded
number separator
// <= JDK12
private const val NBSP = "\u00A0"
then change it to a new number separator
// Java 13 to 17
private const val NNBSP = "\u202F"
Or
To make sure your tests are JDK-independent, use the following method
val separator = DecimalFormatSymbols.getInstance(Locale.FRENCH).groupingSeparator
Full sample code
/**
* @author Nav Singh
*
*/
class FrenchNumberSeparatorTest {
@Test
fun `when Locale is French then check number is properly formatted`() {
val formattedNumber = formatNumberToFrenchLocale(1000)
Assert.assertEquals("1${separator}000", formattedNumber)
}
@Test
fun `when number is formatted for French locale then check the number separator is valid`() {
val formatted = formatNumberToFrenchLocale(1000)
// Hard-coded separator - works only upto JDK12
// Assert.assertEquals(NBSP, formatted.substring(1, 2))
Assert.assertEquals(separator, formatted.substring(1, 2))
}
private fun formatNumberToFrenchLocale(number: Int): String {
val format = NumberFormat.getInstance(Locale.FRANCE)
return format.format(number.toLong())
}
companion object {
// Number separator in Java 8, 11 & 12.
private const val NBSP = "\u00A0"
// Number separator in Java 13 to 17.
private const val NNBSP = "\u202F"
// Get number separator and use it
val separator = DecimalFormatSymbols.getInstance(Locale.FRENCH).groupingSeparator.toString()
}
}