The new Android default project contains two test packages:

  • SRC /androidTest (need a real Android runtime environment, i.e. need to install the startup App)
  • SRC /test (run directly on JVM)

However, if the method we are testing contains only a small number of Android-related classes, such as Android.text.textutils, we do not want to compile and run the app to test, if we do not add other dependencies. Method concat in android.text.textutils not mocked

java.lang.RuntimeException: Method concat in android.text.TextUtils not mocked. See http://g.co/androidstudio/not-mocked for details.

	at android.text.TextUtils.concat(TextUtils.java)
	at com.example.androidunittest.TextUtilsTest.test(TextUtilsTest.java:13)
	at com.example.androidunittest.ExampleUnitTest.url_isCorrect(ExampleUnitTest.java:21)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        ....
Copy the code

After a while, Google found the following solution:

Add two dependencies

Dependencies {testImplementation "org. Robolectric: robolectric: 4.4" testImplementation 'androidx. Test. Ext: junit: 1.1.2'}Copy the code

Rather than using androidTestImplementation note testImplementation,

Then add @runwith (Androidjunit4.class) annotation, run the test and it passes; The complete code is as follows:

package com.example.androidunittest; import android.net.Uri; import android.text.TextUtils; import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; /** * Example local unit test, which will execute on the development machine (host). * * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> */ @RunWith(AndroidJUnit4.class) public class ExampleUnitTest { @Test public void url_isCorrect() { String test = TextUtilsTest.test(); boolean isEmpty = TextUtilsTest.isEmpty(""); Uri uri = Uri.parse("https://stackoverflow.com/questions/53595837/ttt.png"); String segment = uri.getLastPathSegment(); System.out.println("segment: " + segment); assertFalse("segment: " + segment, TextUtils.isEmpty(segment)); assertTrue("isEmpty: ", isEmpty); assertTrue("true: " + test, test.startsWith("ss")); }}Copy the code
package com.example.androidunittest; import android.text.TextUtils; /** * Author: meyu * Date: 4/21/21 * Email: [email protected] */ public class TextUtilsTest { public static String test() { return TextUtils.concat("ss", "null").toString(); } public static boolean isEmpty(String s) { return TextUtils.isEmpty(s); }}Copy the code

Android classes can be run on the JVM. Robolectric simulates Android classes and many view-related shadow classes, which will be studied later.