views:

440

answers:

2

I think I'm not using verify correctly. Here is the test:

@Mock GameMaster mockGM;    
Player pWithMock;

@Before
public void setUpPlayer() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
 pWithMock = new Player(mockGM);
}

@Test
    public void mockDump() {
     pWithMock.testDump();
     verify(mockGM).emitRandom(); // fails
    }

Here is the code it calls:

public boolean testDump() {
 Letter t = tiles.getRandomTile();
 return dump(t);
}

private boolean dump(Letter tile) {
            if (! gm.canTakeDump() || tiles.count() == 0) {
  return false;
 }

 tiles.remove(tile);
 gm.takeTile(tile);
 for (int i = 0; i < 3; i++) {
  tiles.addTile(gm.emitRandom()); // this is the call I want to verify
 }
 return true;
}

Failure trace:

Wanted but not invoked:
gameMaster.emitRandom();
-> at nth.bananas.test.PlayerTest.mockDump(PlayerTest.java:66)

However, there were other interactions with this mock:
-> at nth.bananas.Player.dump(Player.java:45)

    at nth.bananas.test.PlayerTest.mockDump(PlayerTest.java:66)

The call I want to verify is several layers down. Is there a different way to check this?

A: 

I'm not sure to understand what you are doing. Given the following Player class:

public class Player {
    private final GameMaster gm;

    public Player(GameMaster gameMaster) {
        this.gm = gameMaster;
    }

    public void foo() {
        gm.bar(); // this is the call we want to verify
    }
}

And the following GameMaster class:

public class GameMaster {
    public GameMaster() {
    }

    public void bar() {
    }
}

I'd write the test of Player like this:

import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class PlayerTest {

    @Mock
    private GameMaster gm;

    @Test
    public void testFoo() {
        Player player = new Player(gm);
        player.foo();
        verify(gm).bar(); // pass
    }
}
Pascal Thivent
I definitely don't know what I'm doing. How is this different from what I posted?
Rosarch
also, what if the GameMaster class doesn't have a constructor with no args?
Rosarch
@Rosarch *How is that different?* I'm not totally sure as you didn't show all code but, well, this works :) *What if the GameMaster doesn't have a constructor with no args?* Well, this is a sample but if you need to add this constructor to make the code testable, just do it.
Pascal Thivent
ok, but in your example, what if `foo()` calls `odp()`, which then calls `bar()`. Would `verify(gm).bar()` still detect it?
Rosarch
I'm not sure of what `opd()` does but you may need to create a full graph of mocks if this is your question.
Pascal Thivent
`odp()` does nothing but call `bar()`. `void odp() { gm.bar();}`
Rosarch
@Rosarch Isn't that precisely what `foo()` is doing? I don't get the difference.
Pascal Thivent
Right, but `foo()` isn't calling `bar()` directly, whereas `odp()` is.
Rosarch
I don't think I'm still following you and, because I can't reproduce your test, I don't think we'll solve this using the commenting system. Maybe you should post something that readers could reproduce, this would help IMO.
Pascal Thivent
A: 

There is an error in your test method: it's missing a necessary expectation for the GameMaster#canTakeDump(). This method needs to return true when called from the tested method (because of its use in that if statement at line 45).

Rogerio