Amira Elsayed Ismail
Amira Elsayed Ismail

Reputation: 9414

Unit testing in Android Studio gives an error

I am trying to write a unit test for my class, but I am getting the following error

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

at android.text.TextUtils.isEmpty(TextUtils.java)
at com.mvvm.testmvvm.Model.User.isValidUser(User.java:37)
at com.mvvm.testmvvm.LoginViewModelTest.isValidUser_Test(LoginViewModelTest.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)

this is my class

public class User {

    private String  mEmail;
    private String  mPassword;

    public User() {
    }

    public User(String mEmail, String mPassword) {
        this.mEmail = mEmail;
        this.mPassword = mPassword;
    }

    public String getEmail() {
        return mEmail;
    }

    public void setEmail(String mEmail) {
        this.mEmail = mEmail;
    }

    public String getPassword() {
        return mPassword;
    }

    public void setPassword(String mPassword) {
        this.mPassword = mPassword;
    }

    public int isValidUser () {

        if (TextUtils.isEmpty(getEmail()) == true)
            return 0;
        else if (!Patterns.EMAIL_ADDRESS.matcher(getEmail()).matches())
            return 1;
        else if (TextUtils.isEmpty(getPassword()) == true)
            return 2;
        else if (getPassword().length() < 6)
            return 3;
        else
            return -1;
    }
}

and this is my test class

public class LoginViewModelTest {

    @Test
    public void isValidUser_Test() {

        User user = new User("[email protected]", "amira123");
        int result = user.isValidUser();
        assertEquals(4, 2 + 2);
    }

}

Can anyone please tell me what the problem is?

EDIT

@Test
    public void isValidUser_happyCase() {

        User user = new User("[email protected]", "amira123");
        int result = user.isValidUser();
        assertEquals(-1, result);
    }

    @Test
    public void isValidUser_emptyEmail() {

        User user = new User("", "amira123");
        int result = user.isValidUser();
        assertEquals(0, result);
    }

    @Test
    public void isValidUser_invalidEmail() {

        User user = new User("aaaaaaa", "amira123");
        int result = user.isValidUser();
        assertEquals(1, result);
    }

    @Test
    public void isValidUser_emptyPassword() {

        User user = new User("[email protected]", "");
        int result = user.isValidUser();
        assertEquals(2, result);
    }

    @Test
    public void isValidUser_invalidPassword() {

        User user = new User("[email protected]", "111");
        int result = user.isValidUser();
        assertEquals(3, result);
    }

Upvotes: 0

Views: 2081

Answers (1)

Michael Dodd
Michael Dodd

Reputation: 10280

You cannot use classes specific to the Android framework within local JUnit tests (e.g. TextUtils in your case), they are only present as stubs if you enable unitTests.returnDefaultValues = true. From the documentation:

If you run a test that calls an API from the Android SDK that you do not mock, you'll receive an error that says this method is not mocked. That's because the android.jar file used to run unit tests does not contain any actual code (those APIs are provided only by the Android system image on a device).

You've got three options:

  • First is to use the Robolectric testing library, which provides functional versions of Android classes for running in local JUnit tests. This would only need the addition of @RunWith(RobolectricTestRunner.class) at the top of your test.

  • Second is to instead run your tests as Instrumented Unit Tests by placing your test classes under the src/andoidTest folder and running the tests on an actual device or emulator.

  • One last option is to create your own null-safe utility method, as String.isEmpty() can throw a NullPointerException and the Apache StringUtils library is not natively available to Android:


public static boolean isEmpty(@Nullable String in) {
    return in == null || in.isEmpty();
}

I'd advise the first option as you're only using a utility class.

Upvotes: 3

Related Questions