How to mock method e in Log

后端 未结 12 1688
忘掉有多难
忘掉有多难 2020-12-13 03:24

Here Utils.java is my class to be tested and following is the method which is called in UtilsTest class. Even if I am mocking Log.e method as shown below

 @B         


        
相关标签:
12条回答
  • 2020-12-13 03:43

    Thanks to @Paglian answer and @Miha_x64 comment, I was able to make the same thing work for kotlin.

    Add the following Log.kt file in app/src/test/java/android/util

    @file:JvmName("Log")
    
    package android.util
    
    fun e(tag: String, msg: String, t: Throwable): Int {
        println("ERROR: $tag: $msg")
        return 0
    }
    
    fun e(tag: String, msg: String): Int {
        println("ERROR: $tag: $msg")
        return 0
    }
    
    fun w(tag: String, msg: String): Int {
        println("WARN: $tag: $msg")
        return 0
    }
    
    // add other functions if required...
    

    And voilà, your calls to Log.xxx should call theses functions instead.

    0 讨论(0)
  • 2020-12-13 03:49

    Using PowerMock one can mock Log.i/e/w static methods from Android logger. Of course ideally you should create a logging interface or a facade and provide a way of logging to different sources.

    This is a complete solution in Kotlin:

    import org.powermock.modules.junit4.PowerMockRunner
    import org.powermock.api.mockito.PowerMockito
    import org.powermock.core.classloader.annotations.PrepareForTest
    
    /**
     * Logger Unit tests
     */
    @RunWith(PowerMockRunner::class)
    @PrepareForTest(Log::class)
    class McLogTest {
    
        @Before
        fun beforeTest() {
            PowerMockito.mockStatic(Log::class.java)
            Mockito.`when`(Log.i(any(), any())).then {
                println(it.arguments[1] as String)
                1
            }
        }
    
        @Test
        fun logInfo() {
            Log.i("TAG1,", "This is a samle info log content -> 123")
        }
    }
    

    remember to add dependencies in gradle:

    dependencies {
        testImplementation "junit:junit:4.12"
        testImplementation "org.mockito:mockito-core:2.15.0"
        testImplementation "io.kotlintest:kotlintest:2.0.7"
        testImplementation 'org.powermock:powermock-module-junit4-rule:2.0.0-beta.5'
        testImplementation 'org.powermock:powermock-core:2.0.0-beta.5'
        testImplementation 'org.powermock:powermock-module-junit4:2.0.0-beta.5'
        testImplementation 'org.powermock:powermock-api-mockito2:2.0.0-beta.5'
    }
    

    To mock Log.println method use:

    Mockito.`when`(Log.println(anyInt(), any(), any())).then {
        println(it.arguments[2] as String)
        1
    }
    
    0 讨论(0)
  • 2020-12-13 03:53

    If using Kotlin I would recommend using a modern library like mockk which has built-in handling for statics and many other things. Then it can be done with this:

    mockkStatic(Log::class)
    every { Log.v(any(), any()) } returns 0
    every { Log.d(any(), any()) } returns 0
    every { Log.i(any(), any()) } returns 0
    every { Log.e(any(), any()) } returns 0
    
    0 讨论(0)
  • 2020-12-13 03:54

    Another solution is to use Robolectric. If you want to try it, check its setup.

    In your module's build.gradle, add the following

    testImplementation "org.robolectric:robolectric:3.8"
    
    android {
      testOptions {
        unitTests {
          includeAndroidResources = true
        }
      }
    }
    

    And in your test class,

    @RunWith(RobolectricTestRunner.class)
    public class SandwichTest {
      @Before
      public void setUp() {
      }
    }
    

    In newer versions of Robolectric (tested with 4.3) your test class should look as follows:

    @RunWith(RobolectricTestRunner.class)
    @Config(shadows = ShadowLog.class)
    public class SandwichTest {
        @Before
        public void setUp() {
            ShadowLog.setupLogging();
        }
    
        // tests ...
    }
    
    0 讨论(0)
  • 2020-12-13 04:00

    I would recommend using timber for your logging.

    Though it will not log anything when running tests but it doesn't fail your tests unnecessarily the way android Log class does. Timber gives you a lot of convenient control over both debug and production build of you app.

    0 讨论(0)
  • 2020-12-13 04:02

    If your are using the org.slf4j.Logger, then just mocking the Logger in test class using PowerMockito worked for me.

    @RunWith(PowerMockRunner.class)
    public class MyClassTest {
    
    @Mock
    Logger mockedLOG;
    
    ...
    }
    
    0 讨论(0)
提交回复
热议问题