【问题标题】:JUnit4 TextUtils.isEmpty() gives different result than String.isEmpty()JUnit4 TextUtils.isEmpty() 给出的结果与 String.isEmpty() 不同
【发布时间】:2016-04-25 16:27:42
【问题描述】:

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

我正在编写一个单元测试来检查我的 Android 应用程序逻辑。在测试执行期间,我看到它在该行失败:

if (!TextUtils.isEmpty(fromFile))

if 语句 fromFile 之前等于 ""(空字符串),但不知何故它越过了它并与另一个不期望空字符串的逻辑中断。

深入调试我看到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()多做。 任何有关澄清和建议的帮助都会有所帮助。

有人遇到过吗?我应该如何解决它?提前致谢!

【问题讨论】:

    标签: java android string junit is-empty


    【解决方案1】:

    对于任何将要面对它的人:

    在好人的帮助下我已经弄清楚了,它与gradle中的android单元测试配置有关:

    testOptions {
        unitTests.returnDefaultValues = true
    }
    

    这为我提供了一个解决方案:摆脱您正在使用 JUnit(单元测试)测试的业务逻辑中的 android 依赖项。

    我只是用我自己在MyStringUtils.java 类中的方法替换了android.text.TextUtils,效果相同。

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

    【讨论】:

    • 但这是一个解决方案吗?我的意思是,对于这种情况,您只有 TextUtils,但是如果您使用 SparsArrays 和 Android 提供的其他一些自定义实用程序实现呢?
    • 纯 JUnit 测试的想法是它们必须用于 POJO(普通旧 Java 对象)。 SparseArrays 不是旧 Java。如果你有,你可以用robolectric.org,根据谷歌developer.android.com/training/testing/fundamentals.html完全没问题
    【解决方案2】:

    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
    }
    

    【讨论】:

    • 很遗憾我们不使用PowermockmockStatic 不适用。我们转移到了不同​​的架构,我们的 Java 类是 POJO 并且没有任何 android 依赖项。我们还摆脱了诸如“Utils.doSomething”之类的静态方法并删除了单例。这使我们能够更好地控制 DI 和测试覆盖率。据我所知,codecov 仍然不支持PowerMockito。不过谢谢你的回答,我想很多开发者也会觉得它很有用。
    猜你喜欢
    • 1970-01-01
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    相关资源
    最近更新 更多