9

In the middle of a method I'm doing something like this

JSONObject = new JSONObject(json);

Now I'm trying to unit test that using Android Studio and JUnit. Unfortunately, Android Studio won't let me create a real JSONObject instance and ask me to mock it.

What's the simplest way to keep that code and being able to unit test?

Mockito won't help me since it's not able to mock constructors, but it seems PowerMock is the way to go.

StackOverflower
  • 5,463
  • 13
  • 58
  • 89

4 Answers4

10

I've finally used Robolectric. It allows you to run tests simulating real device conditions. This makes unnecessary to mock frameworks classes.

Just need to add robolectric reference to gradle and decorate my test classes with @RunWith(RobolectricTestRunner.class)

Miloš Černilovský
  • 3,846
  • 1
  • 28
  • 30
StackOverflower
  • 5,463
  • 13
  • 58
  • 89
4

You can create a mock JSONObject with the simple code

JSONObject mock = Mockito.mock(JSONObject.class);

Then you can easily mock it's methods such as the field getters, to be able to return whatever you want from the JSONObject.

If the problem is that this JSONObject is created in the middle of a long function, you can extract the JSONObject creation to a collaborator and then mock the collaborator.

MyClass {
   MyClass(JSONObjectCreator creator) {
      this.creator = creator;
   }
   public void doesSomethingWithJSON(String input) {
      //...
      JSONObject jsonObject = creator.createJSONObject(input);
      //...
   }
}
JSONCreator {
   public JSONObject createJSONObject(String input) {
      return new JSONObject(input);
   }
}

In your test you would create a mock JSONObject, and a new MyClass with a mocked JSONObjectCreator. The mocked JSONObjectCreator would return the mock JSONObject.

Andrew R. Freed
  • 357
  • 1
  • 10
  • 1
    I know I can inject a Factory, but it won't to avoid it if possible. Thanks – StackOverflower Nov 13 '15 at 19:37
  • What are you trying to accomplish? I've suggested two ways to create mocks. I am not sure what you want or need your test to do, nor why you want to avoid injecting a factory. – Andrew R. Freed Nov 16 '15 at 03:16
  • I don't want to créate a Factory for every framework component I want to create. I just want to inject a mock on constructor call as explained on question. Thanks – StackOverflower Nov 16 '15 at 12:11
1

If you are using Kotlin and Mockk lib

private val json: JSONObject = mockk(relaxed = true)
Cube
  • 362
  • 4
  • 8
0

There is an alternate way to get the reference of JSONObject in your InjectMock class, Please refer to the below snippet

import org.powermock.api.support.membermodification.MemberModifier;

private final Gson gson = new Gson();

@InjectMocks
private AppleService appleService;

MemberModifier.field(AppleService.class, "gson").set(appleService,gson);