37

I'm trying to print something when running Android Local Unit Test, but nothing's happening. What's the matter? How can I fix it?

I consulted some documents on http://developer.android.com, found that Android Local Unit Test just run on my machine's JVM, the android.jar file that is used to run unit tests does not contain any actual code, so Log.d() print nothing. If i wanna print log, how can i do?

Here is my code, FeedbackModelTest.java located in src/test/main directory.

package com.upward.reader.mvp.model;

import android.util.Log;

import com.upward.reader.mvp.bean.FeedbackBean;
import com.upward.reader.net.RequestJSONCallback;

import org.junit.Test;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class FeedbackModelTest {

@Test
public void postFeedback() throws Exception {
    final String url = "http://test.guguread.com/interface/app/user/feedback?";
    Map<String, String> params = new HashMap<>();
    params.put("content", "content");
    new FeedbackModel().postFeedback(url, params, new RequestJSONCallback<FeedbackBean>() {

        @Override
        public void onResponse(FeedbackBean result) throws IOException {
            Log.d("TAG", result.toString());
        }

        @Override
        public void onFailure(Exception e) {
            e.printStackTrace();
        }

    });
}

}

Will Tang
  • 975
  • 1
  • 7
  • 17
  • If by "local unit test", you mean that you are running the tests directly on your JVM (e.g., `test/` in Android Studio, not `androidTest/`), there is no LogCat, so I would not expect to see that text anywhere. – CommonsWare May 12 '16 at 14:42
  • Yep, I'm running the tests on jvm, the test code located in src/test/java floder. Do you know how to print log in this case? – Will Tang May 12 '16 at 14:48
  • Log prints to LogCat, which I doubt would be running for the local unit test. Not sure, though... – npace May 12 '16 at 14:54
  • Does this answer your question? [Log messages in android studio junit test](https://stackoverflow.com/questions/35562238/log-messages-in-android-studio-junit-test) – hojin Dec 30 '20 at 09:57

5 Answers5

81

You should use standard output, System.out.println("Hello StackOverflow") intead of Log.x(). Then you can see the log info in the run tab. enter image description here

2017/12/16 Update: If you can't see the output on the Run tab, go to Android Monitor tab to find the output instead.

Jeff T.
  • 2,193
  • 27
  • 32
4

I suggest you to use interface:

interface PlatformLog {
    fun e(tag: String, msg: String, throwable: Throwable?=null)
    fun i(tag: String, msg: String)
}

create an interface for example:

in unit tests:

class SystemPlatformLog : PlatformLog {
    override fun i(tag: String, msg: String) {
        println("$tag : $msg")
    }

    override fun e(tag: String, msg: String, throwable: Throwable?) {
        println("$tag : $msg")
    }
}

In android

class AndroidPlatformLog : PlatformLog {
                override fun i(tag: String, msg: String) {
                    Log.i(tag, msg)
                }

                override fun e(tag: String, msg: String, throwable: Throwable?) {
                    Log.e(tag, msg, throwable)
                }
            }

Usage: In android

private val log: PlatformLog = AndroidPlatformLog()

public override fun onCreate(savedInstanceState: Bundle?) {
    log.i(TAG, "onCreate $savedInstanceState")
}

In tests

private val log: PlatformLog = SystemPlatformLog()

@Test
fun `should log in System`() {
    log.i(TAG, "called from tests")
}

OR with dagger2 in two cases:

@Inject lateinit var log: PlatformLog

public override fun onCreate(savedInstanceState: Bundle?) {
    log.i(TAG, "onCreate $savedInstanceState")
}

in tests

class MyTest{

@Inject lateinit var log: PlatformLog

@Before
fun setUp() {
    val component = DaggerTestComponent.builder().testModule(TestModule()).build()
        component.inject(this)
}

@Test
fun `should log in System`() {
    log.i(TAG, "called from tests")
}
@Module
open class TestModule {

    @Provides
    @Singleton
    open fun providePlatformLog(): PlatformLog {
        return SystemPlatformLog()
    }
}
@Singleton
@Component(modules = [TestModule::class])
interface TestComponent {
    fun inject(test: MyTest)
}
NickUnuchek
  • 11,794
  • 12
  • 98
  • 138
2

The Jell T. answer above is right. But if you want to use Timber or Log, you can still do that.

You can search for the logs on the Logcat tab: enter image description here

renatojobal
  • 45
  • 1
  • 7
0

From Unit Testing Support:

The android.jar file that is used to run unit tests does not contain any actual code - that is provided by the Android system image on real devices. Instead, all methods throw exceptions (by default). This is to make sure your unit tests only test your code and do not depend on any particular behaviour of the Android platform (that you have not explicitly mocked e.g. using Mockito). If that proves problematic, you can add the snippet below to your build.gradle to change this behavior:

  android {
  // ...
  testOptions { 
    unitTests.returnDefaultValues = true
  }
}
Luis
  • 3,451
  • 1
  • 27
  • 41
0

If you need to involve some form of Android-related code in your tests (which Log.d is), you can use a testing framework such as Robolectric which is designed to act like the Android.jar code that your code references. By configuring your test runner to run in Robolectric, and setting the proper config flag in robolectric's config annotations, you can enable logging using their logging methods.

Josh Kitchens
  • 1,080
  • 11
  • 18