Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JUnit4 TextUtils.isEmpty() gives different result than String.isEmpty()

I know it's weird, but this is what I have.

enter image description here

I'm writing a unit test to check my logic for an Android application. During the test execution, I see that it fails on that line:

if (!TextUtils.isEmpty(fromFile))

Before that if statement fromFile is equals to "" (empty string), but somehow it passes over it and breaks with another logic that doesn't expect empty string.

Diving into debug I saw that fromFile.isEmpty() returns correct result, but TextUtils.isEmpty(fromFile) says that it's not empty.

Open source code, i see:

public static boolean isEmpty(@Nullable CharSequence str) {
   if (str == null || str.length() == 0)
       return true;
   else
       return false;
}

and String.java:

public boolean isEmpty() {
   return value.length == 0;
}

I have following configutation: jdk 1.8.0_77

I would like to avoid whole logic in the app to support String.isEmpty() just to pass the test, since I need to support code before Android API 9, where String.isEmpty is not available, and also TextUtils.isEmpty() do more. Any help with clarification and suggesttions would be helpful.

Has anyone faced it? How should I fix it? Thanks in advance!

like image 966
Roger Alien Avatar asked Apr 25 '16 16:04

Roger Alien


People also ask

What is TextUtils isEmpty?

isEmpty(CharSequence str) Returns true if the string is null or 0-length. static boolean. isGraphic(CharSequence str) Returns whether the given CharSequence contains any printable characters.

Does TextUtils isEmpty check null?

Yes, TextUtils. isEmpty(string) is preferred. TextUtils will always return a boolean value. In code, the former simply calls the equivalent of the other, plus a null check.


2 Answers

For anyone who will face it in future:

I have figured out this by the help of good man, that it is related to android unit test configuration in gradle:

testOptions {
    unitTests.returnDefaultValues = true
}

Which pointed me to a solution: get rid of android dependencies in you buisness logic that you are testing with JUnit(unit test).

I simply replaced android.text.TextUtils with my own method that is in MyStringUtils.java class, that does the same.

Problem was that by deault Android methods did return deafult values while running unit test, and it didn't actually check fromFile value itself, rather then return stub/default value.

like image 115
Roger Alien Avatar answered Oct 05 '22 04:10

Roger Alien


TextUtils isn't a JUnit method. If you need to manipulate with TextUtils.isEmpty answer or other method, you can mock it like:

mockStatic(TextUtils.class);
when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer(new Answer<Boolean>() {
        @Override
        public Boolean answer(InvocationOnMock invocation) throws Throwable {
            CharSequence str = (CharSequence) invocation.getArguments()[0];
            if (str == null || str.length() == 0)
                return true;
            else
                return false;
        }
    });

Don't forget to add TextUtils to PrepareForTest list:

@PrepareForTest({TextUtils.class})

Also above mentioned method works for returnDefaultValues configuration:

testOptions {
    unitTests.returnDefaultValues = true
}
like image 34
Maxim Shoustin Avatar answered Oct 05 '22 06:10

Maxim Shoustin