【问题标题】:How to handle logging in Android JUnit tests?如何处理 Android JUnit 测试中的日志记录?
【发布时间】:2017-07-26 19:17:51
【问题描述】:

我想在模型类中记录信息 - 不一定用于单元测试目的,而是用于我尝试调试的现实生活场景。

但是,如果我尝试使用 android.util.Log 方法,我会在运行 JUnit 测试时收到以下错误:

java.lang.RuntimeException: Method d in android.util.Log not mocked. See http://g.co/androidstudio/not-mocked for details.

我了解为什么会发生这种情况,我不应该在设计为独立于框架的模型类中使用 Android 框架代码!我并不是真的反对这个错误,而是我试图找到解决这个问题的方法。

我有一个想法,这有意义吗?

按照这些思路创建一个CustomLog 类:

public class CustomLog {
    private static ILogger mLogger;

    public static void setLogger(ILogger logger) {
        mLogger = logger;
    }

    public static void e(String tag, String message) {
        mLogger.e(tag, message);
    }
}

其中ILogger 是一个接口,其中包含执行日志功能所需的方法(e、d 等方法...)

我可以创建一个使用android.util.Log 方法的ILoggerImpl,以及一个简单地打印到System.out.println 和/或什么都不做(或其他任何事情!)的MockLogger 类。

我认为这完全符合我的需求(我需要在生命周期的早期设置我的 CustomLog 类,但这并不是什么大不了的事)。

但是,如果我需要将第三方库/外部代码添加到我的模型类中,如果新库/代码使用 android.util.Log 方法,这可能会以同样的方式再次中断。

那么,有没有我可以使用的“包罗万象”类型的行为?你怎么看?

【问题讨论】:

  • 您可以使用System.out.println(),这可能并不完美,但会显示在测试输出中。
  • 当然。我在这里解释说:“我可以创建一个使用android.util.Log 方法的ILoggerImpl,以及一个简单地打印到System.out.println 和/或什么都不做(或其他任何事情!)的MockLogger 类。” - 我的问题是关于 如何 让它很好地工作。 System.out.println 用于单元测试,android.util.Log 用于调试/发布非单元测试!
  • 哦,对了,对不起。我认为你找到了你能做到的最好的。
  • 也是这么想的 ;) - 但如果可能的话,我想得到更多的想法!不过感谢您的反馈!

标签: android unit-testing junit android-testing


【解决方案1】:

解决您引用的“未模拟”异常的一种方法是use PowerMockito to mock the Logging methods。您可以从this 中获取灵感,而不是像链接答案中解释的那样调用PowerMockito.mockStatic(Log.class);,并将PowerMockito 用于replace() Android.utilLog.vLog.dLog.iLog.e 与将运行 System.out.println 的方法。这允许您在 Android Studio 的运行窗口中查看记录的消息。

String[] logMethods = {"v", "d", "i", "e"};
InvocationHandler systemOutPrintln = new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        StringBuilder messageBuilder = new StringBuilder();
        for (int i = 0; i < args.length; i++) {
            String arg = args[i].toString();
            messageBuilder.append(arg);
            // add separators, ASCII art, ...
        }
        System.out.println(messageBuilder);
        return messageBuilder.toString().length();
    }
};

for (String logMethod : logMethods) {
    replace(method(Log.class, logMethod, String.class, String.class)).with(systemOutPrintln);
    replace(method(Log.class, logMethod, String.class, String.class, Throwable.class)).with(systemOutPrintln);
}

免责声明:我不确定以上是否是最惯用的实现。

【讨论】:

  • 我个人认为这违反了模型代码中不应包含 Android 依赖项的原则,但我认为这工作!
猜你喜欢
  • 1970-01-01
  • 2018-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多