salyela
salyela

Reputation: 1655

Mockito is not mocking my context

I have the following setup

public class Blo{
   private Context mContext;

   public Blo(Context context){
      mContext=context;
   }

   public void updateIfNecessary(Cat cat){
      if(cat.isUpdateNecessary()){
          mContext.getContentResolver().update(cat.getUri(), cat.toContentValues(),null,null);
      }
   }
}

Now I am trying to create a Mockito spy to see if the update is executed.

public class BloTest{
   @Test
   public void testCatNotUpdatesIfUnnecessary(){
      Context context = Mockito.spy(InstrumentationRegistry.getContext());
      Blo blo = new Blo(context);
      Cat cat = createCat();
      cat.setUpdateNecessary(false);
      final int expected = 1;
      Mockito.doReturn(1).when(context).getContentResolver();
      assertEquals(1, blo.updateIfNecessary(cat));
   }
}

Now of course I have no idea if I am doing the test correctly. But even before we get to the test, I am getting error when I try to run the test:

org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: class android.app.ContextImpl.

Mockito can only mock non-private & non-final classes.

How can I set up my test case correctly so as to be able to test both when the update is made and when the update is not made? This is my first time using Mockito.

Upvotes: 0

Views: 2160

Answers (1)

Timothy Truckle
Timothy Truckle

Reputation: 15624

You production code violates the Law of demeter (aka Don't talk to strangers!) You access an indirect dependency here:

mContext.getContentResolver().update()

Because of this you have to do more effort configuring your test case:

   @Rule 
   public MockitoRule mockitoRule = MockitoJUnit.rule(); 
   @Mock
   Context context;
   @Mock
   ContentResolver contentResolver;

   @Test
   public void testCatNotUpdatesIfUnnecessary(){
      doReturn(contentResolver).when(context).getContentResolver()
      Blo blo = new Blo(context);
      Cat cat = createCat();
      cat.setUpdateNecessary(false);

      blo.updateIfNecessary(cat);

      verify(contentResolver)
            .update(cat.getUri(), cat.toContentValues(),null,null);
   }

However,
The better solution of cause is to refactor the production code and inject the instance of ContentResolver directly instead of Context...

Upvotes: 2

Related Questions