简体   繁体   中英

java.lang.RuntimeException: Stub! in Android with Mockito

I have been looking on Google for this error, and most of the answers I have found is to move junit dependence, to the top. Or use another mocking framework. I already moved the dependence and still fails, and the whole project uses mockito and powermock.

This is in resume, the code.

package co.pack.session;

import com.google.gson.JsonObject;
import org.junit.Test;
import co.pack.Session.Organization;
import static org.junit.Assert.assertEquals;

public class TestOrganization {

@Test
public void testLoadJson() {
    JsonObject json = new JsonObject();
    json.addProperty("theme_color", "red");
    Organization organization = new Organization();

    organization.loadFromJson(json);

    assertEquals("red", Organization.getThemeColor());
    }
}

Implementation

public static void loadFromJson(JsonObject json) {
    Organization.name = json.has("name") ? json.get("name").getAsString() : "";
    Organization.image = json.has("image") ? json.get("image").getAsString() : "";

    printActualOrganization();
}

private static void printActualOrganization() {
    Log.i(TAG, "_name_ " + name);
    Log.i(TAG, "_image_ " + image);
}

It fails on a Log line

Log.i(TAG, "_name_ " + name);

And got this

java.lang.RuntimeException: Stub!

at android.util.Log.i(Log.java:9)
at co.mobico.Session.Organization.loadJson(Organization.java:50)
at co.mobico.session.TestOrganization.testLoadJson(TestOrganization.java:28)

Log lines, never causes any error on my test, I don't know what is happening in this case.

You can try add the following options to your app build.gradle .

android {

    testOptions {
        unitTests.returnDefaultValues = true
    }
}

This should prevent you from getting this RuntimeException, because in this case the Android-Methods will return default values. Be aware that this might raise other problems, eg when using TextUtils.equals(...) .

Basically I agree with the strategy to mock every dependency of your unit under test, but you can use the return values as a kind of workaround.

The problem is that you call a method directly on a mock.

You usually don't do that.

Usually you create a normal instance of your class under test (cut) and mocks for the dependencies it communicates with:

@Test public void exampleWithMocks(){
  // arrange
  DataTransferObject dto = new DataTransferObject();
  dto.setSomeProperty(SOME_PRIMITIVE_VALUE_OR_STRING);

  SomeServiceTheCutDependsOn dependency = mock( SomeServiceTheCutDependsOn.class);

  ClassUnderTest cut = new ClassUnderTest(dependency);

  // act
  Object result =  cut.doSomethingWith(dto);

  // assert
  assertThat(result,notNullValue());
  verify(dependency).expectedMethodCall(dto);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM