Question

I am currently trying to do a mock test class of the monopoly game.

We've gotten some instructions on how to set some of it up but maybe we simply misunderstand how JMock works.

We have the Player class which uses takeTurn(). We have Die, Board and Piece which are all interfaces to support the mockery. Then we have the Square class which holds no values but is just there to represent a Square. Maybe we should make it an interface as it holds nothing, but I don't know.

Whatever we do, the test always fails. I've tried to omit parts so that we only do one Expectation as well but no luck there. Are we just misunderstanding JMock completely?

Here is our Player class:

public class Player {

    Die d;
    Piece p;
    Board b;

    void takeTurn(Die d, Piece p, Board b) {
        this.d = d;
        this.p = p;
        this.b = b;

        int i = d.roll();
        int v = d.roll();

        Square newLoc = b.getSquare(p.getLocation(), i + v);
        p.setLocation(newLoc);
    }
}

And here is our PlayerTest class:

public class PlayerTest extends TestCase {

    Mockery context = new Mockery();


    public void testTakeTurn() {
        final Board b = context.mock(Board.class);
        final Piece p = context.mock(Piece.class);
        final Die d = context.mock(Die.class);

        Player pl = new Player();

        context.checking(new Expectations() {{
            exactly(2).of (d).roll();
        }});

        context.checking(new Expectations() {{
            oneOf (p).getLocation();
        }});

        final int diceroll = 5;

        context.checking(new Expectations() {{
            oneOf (b).getSquare(p.getLocation(), diceroll);
        }});

        final Square newLoc = new Square();

        context.checking(new Expectations() {{
            oneOf (p).setLocation(newLoc);
        }});

        pl.takeTurn(d,p,b);

        context.assertIsSatisfied();
    }
}
Was it helpful?

Solution

The idea behind mocking is that you produce fake objects upon which you can set expectations. The expectations include which methods will be called and which results will be returned from those methods.

The latter task is something you've missed in your current code. You need to tell JMock what values are to be returned by the method calls on your mocked objects. If JMock isn't told, it defaults to values such as null, 0, false etc.

For example, you declare that you expect two dice rolls, but you've not provided return values that your mocked Dice object should return. So JMock will just return 0. Later on you assume these two rolls sum to 5, which is wrong.

Your code should be changed to look roughly like (untested):

public class PlayerTest extends TestCase {

    Mockery context = new Mockery();    

    public void testTakeTurn() {
        final Board b = context.mock(Board.class);
        final Piece p = context.mock(Piece.class);
        final Die d = context.mock(Die.class);

        Player pl = new Player();
        final int roll1 = 2;
        final int roll2 = 3;

        context.checking(new Expectations() {{
            exactly(2).of (d).roll();
            will(onConsecutiveCalls(
              returnValue(roll1),
              returnValue(roll2))
        }});

        final Location currentLocation = // set to your desired test loc...    

        context.checking(new Expectations() {{
            oneOf (p).getLocation();
            will(returnValue(currentLocation));
        }});

        final Square newLoc = new Square();

        context.checking(new Expectations() {{
            oneOf (b).getSquare(currentLocation, roll1 + roll2);
            will(returnValue(newLoc));
        }});


        context.checking(new Expectations() {{
            oneOf (p).setLocation(newLoc);
        }});

        pl.takeTurn(d,p,b);

        context.assertIsSatisfied();
    }
}

Much as I used to love JMock, I have to agree with the comments that Mockito is far friendlier to use. If you are just starting with mocking, now might be a good time to switch.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top