I am writing a class which handles formatting input text with given pattern.
I am using android.icu.text.DecimalFormat
and android.icu.text.DecimalFormatSymbols
(I used the java.text.Decimalformat
before but it did not worked correctly on the real android device so I switch to use android.icu.text.*
classes)
I am facing some issues:
At first It throws Method ... is not mocked.
I fixed this one by add the testOptions in the build.gradle
file. But then the DecimalFormat instance always returns null
.
I tried every thing and It still does not accept my test case. Please help me. Thank you very much
My class:
import android.icu.text.DecimalFormat;
import android.icu.text.DecimalFormatSymbols;
import androidx.annotation.NonNull;
import java.util.Locale;
public class NumberFormatter {
public String format(String inputText, String pattern){
DecimalFormatSymbols decimalFormatSymbol = getDefaultDecimalFormatSymbols();
DecimalFormat decimalFormat = getDecimalFormat(pattern, decimalFormatSymbol);
double value = Double.parseDouble(inputText);
return decimalFormat.format(value);
}
@NonNull
DecimalFormat getDecimalFormat(String pattern, DecimalFormatSymbols decimalFormatSymbol) {
return new DecimalFormat(pattern, decimalFormatSymbol);
}
@NonNull
DecimalFormatSymbols getDefaultDecimalFormatSymbols() {
DecimalFormatSymbols decimalFormatSymbol = new DecimalFormatSymbols(Locale.getDefault());
decimalFormatSymbol.setDecimalSeparator('.');
decimalFormatSymbol.setGroupingSeparator(',');
return decimalFormatSymbol;
}
}
My test class:
import android.icu.text.DecimalFormat;
import android.icu.text.DecimalFormatSymbols;
import org.junit.Assert;
import org.junit.Test;
public class NumberFormatterTest {
@Test
public void format_givenInputStringAndPatternString_shouldReturnCorrespondingFormattedString(){
String pattern = "#,###.##";
String inputString = "1000.12";
String expect = "1,000.12";
String actual = new NumberFormatter().format(inputString, pattern);
Assert.assertEquals(expect, actual);
}
}
At first it showed this error
Method setDecimalSeparator in android.icu.text.DecimalFormatSymbols not mocked. See http://g.co/androidstudio/not-mocked for details.
java.lang.RuntimeException: Method setDecimalSeparator in android.icu.text.DecimalFormatSymbols not mocked. See http://g.co/androidstudio/not-mocked for details.
After adding to gradle file like this:
testOptions {
unitTests.returnDefaultValues = true
}
Then is always return NULL
expected:<1,000.12> but was:<null>
Expected :1,000.12
Actual :null
<Click to see difference>
java.lang.AssertionError: expected:<1,000.12> but was:<null>
at org.junit.Assert.fail(Assert.java:89)
at org.junit.Assert.failNotEquals(Assert.java:835)
at org.junit.Assert.assertEquals(Assert.java:120)
at org.junit.Assert.assertEquals(Assert.java:146)
I tried to add testOptions
in to build.gradle
I tried to mock the DecimalFormat object
I expected that it could return some object with my settings but it always return null
When you're using android classes in your unit tests, they are actually mocks, not real objects. The error you're seeing indicates that you're trying to access mocked android framework object, in your instance DecimalFormat.
You can either change android classes to java classes, as JakeB suggested or you can use some framework like Robolectric to make android framework partially work in unit tests.