4

EDIT

When reading the FAQ, it gave me some idea about what could possibly cause an issue here. Just to give it a try, I changed the visibility of the stubbed method open() to public and it was executed as expected, without any exception thrown.

I'm not sure if it's a bug or the desired behaviour of version 1.10.19.

ORIGINAL POST

In my Android project, I'm using Mockito to ease the implementation of some (instrumentation) tests. I was able to mock some non-void methods, but didn't figured out how to properly stub a void method.

I'm trying to test a class House. A House has an attribute of type Door and a method openDoor(). A Door and an attribute of type Handle and a method open(). When I invoke the openDoor(), I would like to check if open() was called, so I wrote this code:

@Test
public void testOpenDoorInitial() {
    Door stubbedDoor = mock(Door.class);
    doNothing().when(stubbedDoor).open();
    myHouse.setDoor(stubbedDoor); //myHouse has been initialized
    myHouse.openDoor();
    verify(stubbedDoor, times(1)).open();
}

public class House {
   Door door;
   //rest of code       
   void setDoor(Door d){
      door = d;
   }
   void openDoor(){
      // some conditions
      door.open();
   }
}

public class Door {
   Handle handle;
   //... rest of code
   void open(){
      handle.tryToUse(); //Throws NullPointException
   }
}

The problem is that a NullPointerException is thrown on line doNothing.when(stubbedDoor).open();, telling me that handle is null. doNothing() seems to actually call open(), which I don't expect.

Does anyone has an idea about the source of this problem ? I'm new to Mockito, so I could have missed something obvious.

To enable Mockito in instrumentation testing, I imported the following modules.

androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile "com.crittercism.dexmaker:dexmaker:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-dx:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-mockito:1.4" 
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Gordak
  • 2,060
  • 22
  • 32

2 Answers2

2

Try to use a newer version, you are using 1.10.19. I am not sure but it seems this issue was solved after, as you can see here. Here you can find the version list.

kiuby_88
  • 334
  • 1
  • 6
  • 18
2

This may be related to Mockito's issue 212, in which package-private parent classes can cause mocks to fail because Mockito couldn't stub the hidden methods. (This may be related to synthetic methods that the compiler introduces to work around visibility complications in the class hierarchy.)

Mockito 2.0 solves this problem by switching from CGLIB to ByteBuddy; I don't remember whether ByteBuddy was a part of any 1.x release. However, you're using Mockito with DexMaker instead, which may have a similar problem.

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Hey, thank you for the info. Indeed it seems that method visibility at least affects Mockito's behaviour. After other tests, it seems that class visibility also affects Mockito. Note that the class has no parent ;) I will try Mockito 2.x when it comes out of beta, but for now I will stick to version 1.10.19. I guess that DexMaker doesn't simplify Mockito's job in that matter and may also be a potential source of issues. – Gordak Jun 23 '16 at 06:33
  • Hey Jeff. I tried to use Mockito 2.x, but it seems difficult to integrate it in Android : ie http://stackoverflow.com/questions/31409458/mockito-abstractmethoderror-on-initmocks Any piece of advice on this subject ? Do you use Mockito 2.x in Android (instrumented) tests ? I think I'm just doing something wrong and should in fact write unit tests. – Gordak Jun 23 '16 at 06:55
  • @Gordak Switching to Mockito 2.0 beta won't help, because the change that helped—even though the problem is solved in ByteBuddy, it's not solved in the Android code-generation library DexMaker (which Mockito has to use in instrumentation tests instead of CGLIB or ByteBuddy, because Android requires `dex` files and not `class` files). I bring up issue 212 not because it's an exact match, but only because it's evidence that _in some code-generation libraries restricted visibility can cause surprising and poorly-explained failures to mock_. – Jeff Bowman Jun 24 '16 at 17:46
  • Thank you for the clarification. So I'll just write unit tests, where I don't need any translation from class to dex format. I guess I should have done that from the very beginning. #NewbieProgramming – Gordak Jun 27 '16 at 08:02