JUnit4的TextUtils.isEmpty()和String.isEmpty()的结果不同

9

我知道这很奇怪,但这就是我所拥有的。

enter image description here

我正在编写一个单元测试来检查我的Android应用程序的逻辑。在测试执行过程中,我发现它在以下行上失败:
if (!TextUtils.isEmpty(fromFile))
在这个if语句之前,fromFile等于""(空字符串),但不知何故它通过了这个if语句并且在不期望空字符串的另一个逻辑中出现错误。
通过调试,我发现fromFile.isEmpty()返回正确的结果,但是TextUtils.isEmpty(fromFile)却说它不为空。
查看开源代码,我看到:
public static boolean isEmpty(@Nullable CharSequence str) {
   if (str == null || str.length() == 0)
       return true;
   else
       return false;
}

和 String.java:

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

我有以下配置: jdk 1.8.0_77
我想避免在应用程序中实现整个逻辑以支持String.isEmpty(),仅为了通过测试,因为我需要支持Android API 9之前的代码,其中String.isEmpty不可用,并且TextUtils.isEmpty()执行更多操作。 任何关于澄清和建议的帮助都将是有益的。
有人面临过这个问题吗?我该如何解决它?提前致谢!
2个回答

12

对于将来会遇到此问题的任何人:

我通过好心人的帮助弄清楚了,这与Gradle中的Android单元测试配置有关:

testOptions {
    unitTests.returnDefaultValues = true
}

这启示我一个解决方案:在使用 JUnit(单元测试)时,摆脱你的业务逻辑中的安卓依赖。

我简单地用我的自定义方法替换了 android.text.TextUtils,该方法在 MyStringUtils.java 类中,实现相同的功能。

问题在于,在运行单元测试时,默认情况下 Android 方法会返回默认值,并未实际检查 fromFile 值本身,而是返回存根/默认值。


但这是一个解决方案吗?我的意思是对于这种情况,您只有TextUtils,但如果您使用由Android提供的SparsArrays和其他自定义实用程序实现呢? - X-HuMan
1
纯JUnit测试的想法是它们必须针对POJO(普通旧Java对象)使用。SparseArrays不是旧Java。如果您有它,可以使用http://robolectric.org/,这在谷歌https://developer.android.com/training/testing/fundamentals.html上完全可以接受。 - Roger Alien

5

TextUtils 不是 JUnit 方法。如果你需要操作 TextUtils.isEmpty 或其他方法的答案,你可以像这样模拟它:

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;
        }
    });

不要忘记将 TextUtils 添加到 PrepareForTest 列表中:
@PrepareForTest({TextUtils.class})

上述方法同样适用于returnDefaultValues配置:

testOptions {
    unitTests.returnDefaultValues = true
}

1
很遗憾,我们不使用PowermockmockStatic也不适用。我们转向了不同的架构,其中我们的Java类是POJO,没有任何Android依赖项。我们还放弃了像'Utils.doSomething'这样的静态方法和单例模式。这使我们更加掌控DI和测试覆盖率。据我所知,codecov仍然不支持PowerMockito。但是感谢您的回答,我想很多开发人员也会觉得它有用。 - Roger Alien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接