如何处理 Android JUnit 测试中的日志记录?

Zac*_*ach 7 junit android unit-testing android-testing

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

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

java.lang.RuntimeException: Method d in android.util.Log not mocked. See http://g.co/androidstudio/not-mocked for details.
Run Code Online (Sandbox Code Playgroud)

我明白为什么会发生这种情况,我不应该在设计为独立于框架的模型类中使用 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

ILogger具有执行日志功能所需方法的接口在哪里(e、d 等方法...)

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

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

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

那么,是否有我可以使用的“一网打尽”类型的行为?你怎么认为?

m01*_*m01 0

解决您引用的“未模拟”异常的一种方法是使用 PowerMockito 来模拟Logging 方法您可以从中汲取灵感,并将 PowerMockito 与将运行的方法一起使用,而不是按照链接答案PowerMockito.mockStatic(Log.class);中的说明进行调用。这允许您在 Android Studio 的“运行”窗口中查看记录的消息。replace() Android.utilLog.vLog.dLog.iLog.eSystem.out.println

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);
}
Run Code Online (Sandbox Code Playgroud)

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