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
Extending the answer from kosiara for using PowerMock and Mockito in Java with JDK11 to mock the android.Log.v
method with System.out.println
for unit testing in Android Studio 4.0.1.
This is a complete solution in Java:
import android.util.Log;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
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.ArgumentMatchers.any;
@RunWith(PowerMockRunner.class)
@PrepareForTest(Log.class)
public class MyLogUnitTest {
@Before
public void setup() {
// mock static Log.v call with System.out.println
PowerMockito.mockStatic(Log.class);
Mockito.when(Log.v(any(), any())).then(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
String TAG = (String) invocation.getArguments()[0];
String msg = (String) invocation.getArguments()[1];
System.out.println(String.format("V/%s: %s", TAG, msg));
return null;
}
});
}
@Test
public void logV() {
Log.v("MainActivity", "onCreate() called!");
}
}
Remember to add dependencies in your module build.gradle file where your unit test exists:
dependencies {
...
/* PowerMock android.Log for OpenJDK11 */
def mockitoVersion = "3.5.7"
def powerMockVersion = "2.0.7"
// optional libs -- Mockito framework
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
// optional libs -- power mock
testImplementation "org.powermock:powermock-module-junit4:${powerMockVersion}"
testImplementation "org.powermock:powermock-api-mockito2:${powerMockVersion}"
testImplementation "org.powermock:powermock-module-junit4-rule:${powerMockVersion}"
testImplementation "org.powermock:powermock-module-junit4-ruleagent:${powerMockVersion}"
}
Use PowerMockito.
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassNameOnWhichTestsAreWritten.class , Log.class})
public class TestsOnClass() {
@Before
public void setup() {
PowerMockito.mockStatic(Log.class);
}
@Test
public void Test_1(){
}
@Test
public void Test_2(){
}
}
Mockito doesn't mock static methods. Use PowerMockito on top. Here is an example.
This worked out for me. I'm only using JUnit and I was able to mock up the Log
class without any third party lib very easy. Just create a file Log.java
inside app/src/test/java/android/util
with contents:
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;
}
// add other methods if required...
}
Using PowerMockito:
@RunWith(PowerMockRunner.class)
@PrepareForTest({Log.class})
public class TestsToRun() {
@Test
public void test() {
PowerMockito.mockStatic(Log.class);
}
}
And you're good to go. Be advised that PowerMockito will not automatically mock inherited static methods, so if you want to mock a custom logging class that extends Log, you must still mock Log for calls such as MyCustomLog.e().
You can put this into your gradle script:
android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
That will decide whether unmocked methods from android.jar should throw exceptions or return default values.