【问题标题】:Test a class that calls static wrapper methods测试一个调用静态包装器方法的类
【发布时间】:2017-05-04 12:56:38
【问题描述】:

我有一个 android Log 的静态包装类。

看起来像这样(简化):

// Source: https://github.com/ccrama/Slide/blob/master/app/src/main/java/me/ccrama/redditslide/util/LogUtil.java
public class LogUtil {
    private static final int CALLING_METHOD_INDEX;    

    static {
        int i = 1;
        for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
            i++;
            if (ste.getClassName().equals(LogUtil.class.getName())) {
                break;
            }
        }
        CALLING_METHOD_INDEX = i;
    }

    public static String getTag() {
        final StackTraceElement ste = Thread.currentThread().getStackTrace()[CALLING_METHOD_INDEX];
        return "(" + ste.getFileName() + ":" + ste.getLineNumber() + ")";
    }

    public static void v(String message) {
        Log.v(getTag(), message);
    }
}

我的问题:我正在测试另一个调用此方法的方法 LogUtil.v() 的方法。

如果可能的话,有没有办法用 Mockito 而不是 Powermock(ito) 来测试另一种方法?

目前它会抛出 LogUtil.v not mocked 异常。

我读到如果我必须使用 PowerMockito,我做错了(=> 没有遵循 TDD)。

【问题讨论】:

  • 我认为模拟背后的基本思想(在他们添加“帮助”函数之前)是模拟代表您创建对象。使用静态方法你不需要对象,所以你不需要模拟。您可以只使用 LogUtil.getTag() 并验证它是否返回有效数据。但这只是我的观点,所以也许有人会有更好的答案。
  • 也许我在这里一无所知,但是在测试其他方法时您的问题到底是什么?这个方法在这里调用你的方法是如何阻止你测试它的?
  • @FlorianSchaetz 这样的 static 初始化块总是带有一定的风险。根据确切的内容,已经 加载 具有此类初始化的类可能会破坏您。这就是 static 名声如此糟糕的原因之一:如果使用不当,您可能会使其他人的单元测试变得比应有的困难得多。相信我,去过那里。
  • 我知道一般静态的问题是什么,但问题是,在这个例子中,实际问题是什么,因为我没有看到任何实际上会破坏测试的代码,但是也许我只是一无所知。
  • 可能是Log.v(getTag(), message); ...但@FlorianSchaetz 你说得对...

标签: java android testing junit mockito


【解决方案1】:

(免责声明:我是那些告诉人们不要使用 PowerMock(ito) 的人之一)

话虽如此:当您使用无法更改的 3rd 方库时,使用 PowerMock(ito) 可能是一个合理的选择。

本质上,你只有两个选择:

  • 如前所述;选择允许模拟 static 方法的框架;并且允许您防止此类静态初始化代码在您的单元测试环境中执行。有 PowerMock(ito),还有JMockit
  • 或者,您可以围绕这些类构建一个小型包装器;然后确保所有您的自己的代码仅适用于这些包装器。

因此,您必须评估两种方法的优缺点;并选择对您和您的团队“效果更好”的那个。就我个人而言,我总是选择选项 2。当然,这只有在编写 new 代码时才有可能。

实际上,为了用您自己的包装器替换那些静态调用而对整个代码库进行大规模重构并不是一件轻松的事情。

【讨论】:

  • 感谢您的冗长回复!我目前确实正在重构我的代码以使其可测试(TDD :D),并且我正在尝试了解基础知识。看起来将unitTests.returnDefaultValues = true 添加到 build.gradle 修复了它,我的静态包装器不是问题。
猜你喜欢
  • 2021-10-11
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多