2

I am trying to write a Unit Test (Not instrumented) for Android using JUnit and Mockito.

Some context: I am testing a class that depends heavily on a view and I cannot / don't want to actually inflate the view during the test. At one point, my class-to-test wants to use the width of the view and I have defined a (public) method that the class is using to get the width at runtime (getWidth()).

In my test, I want to use Mockito to mock the getWidth() method - only. (While having the rest of the class behave the same way). Just to clarify: One method in my Class calls getWidth() and I want it to return a mocked value during testing.

So I tried instantiating the Class using the Mockito.spy() method, but I don't know if this is the correct approach (it doesn't work) or if there is something else I should do.

My current code:

mGraph = Mockito.spy(new Graph(xAxis, leftAxis, null, false, new Graph.Style(), curve));
Mockito.when(graph.getGraphWidth()).thenReturn(400);

I get the following error message, though I don't know if it's relevant or just another error:

java.lang.IllegalArgumentException: dexcache == null (and no default could be found; consider setting the 'dexmaker.dexcache' system property)

Joakim
  • 3,224
  • 3
  • 29
  • 53

2 Answers2

5

I solved this problem by changing my build.gradle from this

testCompile ('junit:junit:4.12',
             'com.google.dexmaker:dexmaker-mockito:1.0',
             'com.google.dexmaker:dexmaker:1.0')

to this

testCompile ('junit:junit:4.12',
             'org.mockito:mockito-core:1.9.5')

I guess that this could be because the dex-dependencies should only be used with androidTestCompile-tag.

Joakim
  • 3,224
  • 3
  • 29
  • 53
3

Your spy syntax is correct, but you have two hazards:

  1. You may also need some manual configuration as Adil Hussain posted in this SO answer:

    System.setProperty(
        "dexmaker.dexcache",
        getInstrumentation().getTargetContext().getCacheDir().getPath());
    
  2. Beware that

    Mockito.when(graph.getGraphWidth()).thenReturn(400);
    

    ...contains a call to:

                 graph.getGraphWidth()
    

    that Mockito will call before stubbing. This is probably fine for this call, but in cases where the real method call will throw an exception, Mockito.when syntax is not helpful. Instead, use doReturn:

    Mockito.doReturn(400).when(graph).getWidth();
    

    Note that the call to when only addresses the graph, not the entire method call, which allows Mockito to disable all behavior (including calling the real method) and only use the method call to identify the method.

Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Thank you for your input, that would definetly have been have problem! However, my problem with your manual configuration in (1) is that i *do not* run an instrumented test - and I don't want to. So I cannot use the instrumentation for that. – Joakim Nov 20 '15 at 08:13
  • 1
    Oh! In that case the problem is much more obvious: You CANNOT use dexmaker in JVM based tests. Make sure it is NOT on the classpath and that your version's normal dependencies ARE on it. – Jeff Bowman Nov 20 '15 at 15:12
  • Yes I realized that and added as an answer... But it wasn't stated anywhere... Thanks for your help – Joakim Nov 21 '15 at 15:03