Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito is not mocking a call

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.

like image 333
Th3sandm4n Avatar asked Feb 25 '23 06:02

Th3sandm4n


2 Answers

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

like image 176
Thomas Dufour Avatar answered Mar 03 '23 20:03

Thomas Dufour


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"));
    }
}
like image 29
Tarek Avatar answered Mar 03 '23 18:03

Tarek