在android studio junit test中记录消息

dan*_*iel 13 junit android logcat android-studio

有没有办法在Android Studio中运行JUnit(方法)测试时打印出Logcat(Log.i,Log.d)消息?

我可以看到System.out.print消息但没有logcat打印输出.

在运行配置(Android Studio的GUI窗口)中,有针对Android测试的测试的logcat选项,但不适用于JUnit测试.

这有可能吗?谢谢你的任何提示!

Vas*_*liy 11

在单元测试中不会看到Logcat输出,因为Logcat是Android功能 - JUnit测试只能使用标准Java,因此Android功能不起作用.

您在单元测试中可以做的是将"测试双打"注入到测试组件中.但是Log.x调用是静态的,所以你不能覆盖它们(没有解析为例如PowerMock,你应该不惜一切代价避免).

因此,第一步是引入一个非静态类,它将作为Log.x调用的代理:

/**
 * This class is a non-static logger
 */
public class Logger {

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

    public void w(String tag, String message) {
        Log.w(tag, message);
    }

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

    public void d(String tag, String message) {
        Log.d(tag, message);
    }
}
Run Code Online (Sandbox Code Playgroud)

Log.x现在在您呼叫的每个地方使用此课程.

第二步是编写Logger重定向到标准输出的测试双重实现:

public class UnitTestLogger extends Logger{

    @Override
    public void e(String tag, String message) {
        System.out.println("E " + tag + ": " + message);
    }

    // similar for other methods
}
Run Code Online (Sandbox Code Playgroud)

最后一步是注入UnitTestLogger而不是Logger单元测试:

@RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {

    private Logger mLogger = new UnitTestLogger();

    private SomeClass SUT;

    @Before
    public void setup() throws Exception {
        SUT = new SomeClass(/* other dependencies here */ mLogger);
    }

}
Run Code Online (Sandbox Code Playgroud)

如果您想严格遵守OOP概念,可以为Logger和提取通用接口UnitTestLogger.

也就是说,我从来没有遇到过Log.x在单元测试中调查调用的需要.我怀疑你也不需要它.您可以在调试模式下运行单元测试,并在调试器中逐行遍历代码,这比尝试调查logcat输出快得多...

一般建议:

如果您正在测试的代码包含Log.x静态调用,并且您的单元测试没有崩溃 - 那么您就会遇到问题.

我猜想要运行所有测试Robolectric,或者你在build.gradle中有这个语句:unitTests.returnDefaultValues = true.

如果你运行所有测试Robolectric,那么它只是效率低下,但如果所有Android调用都返回默认值,那么测试套件是不可靠的.我建议你在继续进行之前解决这个问题,因为它将来会以某种方式咬你.

  • 您只需命名Logger实例Log而不是mLogger即可完全避免更改Log调用。 (2认同)

hoj*_*jin 6

根据这篇文章https://medium.com/@gal_41749/android-unitests-and-log-class-9546b6480006

只需创建Log.java文件并将其放入test/java/android/util/.

package android.util;

public class Log {
    public static int d(String tag, String msg) {
        System.out.println("DEBUG: " + tag + ": " + msg);
        return 0;
    }

    public static int i(String tag, String msg) {
        System.out.println("INFO: " + tag + ": " + msg);
        return 0;
    }

    public static int w(String tag, String msg) {
        System.out.println("WARN: " + tag + ": " + msg);
        return 0;
    }

    public static int e(String tag, String msg) {
        System.out.println("ERROR: " + tag + ": " + msg);
        return 0;
    }
    
}
Run Code Online (Sandbox Code Playgroud)


use*_*985 2

我一直在寻找同样的东西,但没有找到直接的答案。我知道这个问题已经有一年多了,但仍然最好在这里有一个答案以供将来参考。

android.util.Log 类直接记录到 Logcat,并且在本地 JVM 上运行单元测试时 android.util.Log 的实现不可用。尝试在单元测试中使用 Log 类时,您会收到错误,因为“用于运行单元测试的 android.jar 文件不包含任何实际代码(这些 API 仅由设备上的 Android 系统映像提供) ”。
请参阅有关单元测试的 Android 文档

因此,如果您确实想使用 android.util.Log,您需要在本地模拟它并利用 System.out.print 打印到控制台。首先,将 PowerMockito 添加到您的项目中。如果您使用 Gradle,则只需添加以下依赖项:

testCompile 'junit:junit:4.12'
testCompile 'org.powermock:powermock:1.6.5'
testCompile 'org.powermock:powermock-module-junit4:1.6.5'
testCompile 'org.powermock:powermock-api-mockito:1.6.5'
Run Code Online (Sandbox Code Playgroud)

接下来,我使用 Steve 的答案弄清楚如何使用 Mockito 返回传递到模拟对象的参数。

结果是这样的:

import android.util.Log;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.mockito.Matchers.anyString;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Log.class})
public class SomeUnitTest {

    @Test
    public void testSomething() {
        System.out.println("Running test"); 
        PowerMockito.mockStatic(Log.class);

        // Log warnings to the console        
        when(Log.w(anyString(), anyString())).thenAnswer(new Answer<Void>()      {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Object[] args = invocation.getArguments();
                if (args.length > 1) { //cause I'm paranoid
                    System.out.println("Tag:" + args[0] + " Msg: " + args[1]);
                }
                return null;
            }
        });
        Log.w("My Tag", "This is a warning");
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这对某人有帮助!

  • “我建议不惜一切代价避免 PowerMock” - 好吧,你解释一下原因怎么样? (3认同)