Android Studio 单元测试报错 Method d in android.util.Log not mocked

  1. 在学习Android Studio进行单元测试的时候(Junit4), 进行如下测试时候

    @Test
    public void testParseLastPage() throws Exception {

        String page = ToCollection.parseLastPage(Data.data);
        assertEquals("Voucher.aspx?page=5", page);

    }

报了错误如下

java.lang.RuntimeException: Method d in android.util.Log not mocked. See http://g.co/androidstudio/not-mocked for details.
    at android.util.Log.d(Log.java)
    at com.lantern.tools.Log.d(Log.java:21)
    at com.lantern.data.deal.ToCollection.parseLastPage(ToCollection.java:36)
    at com.lantern.data.deal.ToCollectionTest.testParseLastPage(ToCollectionTest.java:33)


Process finished with exit code 255
  1. 我个人的理解,是因为没有找到Log.d进行调用,还是因为在测试类ToCollectionTest在的包中也创建Log类,有点不明白为什么出现这个问题:

    1. 因为这个里面用到了要测试的方法是ToCollection类里面的parseLastPage(String html),解释:获得网页源代码,从html中解析出一个标签值;但是这个方法中当时写的时候,里面有自定义的Log类,方法的代码如下

   public static String parseLastPage(String html) {

        Log.d("Tag", "解析首页账单数据-解析a标签,获得对应数据");
        Document doc = html2Document(html);
        String page = "";

        try {
            page = doc.select("a").last().attr("href");
        } catch (NullPointerException e) {
            Log.d("String", "因为页面数量只有一个");
        }

        return page;

    }
  1. 自定义的Log类是为了方便控制开发和发布时候的日志打印的,如下

public class Log {
    private static final boolean DEBUG = true;

    public static void i(String tag, String msg) {
        if (DEBUG)
            android.util.Log.i(tag, msg);
    }

    public static void e(String tag, String msg) {
        if (DEBUG)
            android.util.Log.e(tag, msg);
    }

    public static void d(String tag, String msg) {
        if (DEBUG)
            android.util.Log.d(tag, msg);
    }

    public static void v(String tag, String msg) {
        if (DEBUG)
            android.util.Log.v(tag, msg);
    }

    public static void w(String tag, String msg) {
        if (DEBUG)
            android.util.Log.w(tag, msg);
    }
}
  1. build.gradle如下

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.easy"
        minSdkVersion 14
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }


}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile files('src/main/libs/jsoup-1.8.3.jar')
}
repositories {
    maven { url "https://jitpack.io" }
}


dependencies {
    compile 'com.github.PhilJay:MPAndroidChart:v2.1.5'
//    testCompile 意思为,test模式下依赖某一个库,该库不会在我们正式发布时打包到我们的程序中,作用和 debugCompile 类似。
    testCompile 'junit:junit:4.12'
    testCompile "org.mockito:mockito-core:1.9.5"
}
阅读 23.4k
3 个回答
新手上路,请多包涵

Log类是android sdk的api,用Junit做单元测试,只能用纯java API,否则会报错。如果用JUnit做java层面的单元测试时,会调用Android 层面的SDK就会报错,要求mock对象,现在如果对mock过程不熟悉,最简单的处理方法是用框架Robolectric,不再需要Mock框架,可以模拟出android运行环境。如果单元测试中有android相关的代码;推荐采用单元测试框架Robolectric,Robolectric可以检测到你调用了Android相关的类,然后截取这些调用,转到他们的Shadow类。Robolectric的做法是通过实现一套JVM能运行的Android代码,然后在unit test运行的时候去截取android相关的代码调用,然后转到他们的他们实现的代码去执行这个调用的过程

在写本地单测的时候,会遇到android.jar某个方法没有被Mock的情况,此时可以通过如下配置:

android {
  // ...
  testOptions { 
    unitTests.returnDefaultValues = true
  }
}

让Gradle系统为该方法返回默认值

你试试这个,应该是可以的

System.out.print(message);可以用这个封装一下
在我的项目里,每个模块的日志实现方法都是注入的比如:

  BaseServiceImpl.init(new BaseServiceImpl.ServiceDelegate() {
            @Override
            public void log(String message) {
                System.out.print(message);
            }
        });

这样在单元测试时可以随时修改实现

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进