Mockito is not mocking a call

21,210

Solution 1

public class TestClass {
  private TestMachine tester;
  public void setUp() {         
    tester = mock(TestMachine.class);     
  }      

  public void testOne() {
          when(tester.ping(anyString()).thenReturn(-1);
          assertFalse(tester.machineIsGood("testHost"));
     }
} 

Solution 2

In my experience, you should not use mocks to test interactions between methods in the same class.

What this tells us is that you should decouple your SUT (system under test) from the external dependency that you need to replace with a test double (the ping that you do not want to call "for real" in your unit tests).


public class Pinger {
    public int ping(String host) {
        // yadda yadda
    }
}

public class TestMachine {

    private final Pinger pinger;

    public TestMachine(final Pinger pinger) {
        this.pinger = pinger;
    }

    public boolean machineIsGood(host) {
        // blah blah
        int val = pinger.ping(host);
        // blah blah blah
        return val == 0;
    }
}

public class TestMachineTest {
    @Test
    public void testOne() {
        final Pinger pinger = mock(Pinger.class);
        when(pinger.ping(anyString())).thenReturn(-1);

        TestMachine tester = new TestMachine(pinger);
        assertFalse(tester.machineIsGood("testHost"));
    }
}

HTH

Solution 3

When you use Mockito.spy(), use the Mockito.doReturn() for non-void methods or Mockito.doNothing() for void methods.

In your case:

public class TestClass {
    public void setUp() {
        TestMachine tester = Mockito.spy(new TestMachine());
    }

    public void testOne() {
        doReturn(-1).when(test).ping(Mockito.anyString())
        assertFalse(tester.machineIsGood("testHost"));
    }
}
Share:
21,210
Th3sandm4n
Author by

Th3sandm4n

Updated on July 09, 2020

Comments

  • Th3sandm4n
    Th3sandm4n almost 4 years

    One of the functions I'm testing is sshing into a machine. I want to mock the ping method, that actually tries to ssh into a machine, since I am not really sshing into a machine.

    class I am testing:

    public class TestMachine {
        public int ping(host){
        }
    
        public boolean machineIsGood(host) {
            blah blah
            int val = ping(host);
            blah blah blah
            if(val != 0) return false;
            return true;
        }
    }
    

    The test class goes something like this:

    public class TestClass {
        public void setUp() {
            TestMachine tester = spy(new TestMachine());
        }
    
        public void testOne() {
             when(test.ping(anyString()).thenReturn(-1);
             assertFalse(tester.machineIsGood("testHost"));
        }
    {
    

    The problem is that when I am running them locally, they work just fine, but on our autobuild system it seems like it is actually calling the real ping and getting an Authentication Exception. I'm going to use mock() instead of spy() since I've read it's a bit weird, but I just can't understand what makes a difference in that it is actually calling the method! Just wondering if anyone else has any insight.

  • Th3sandm4n
    Th3sandm4n over 13 years
    The only problem is that in ping it uses some private variables (that are not instantiated because the class is mocked). Looks like I'm just going to have to restructure the code to make it more test friendly.