Does mockito have an equivalent idiom to jMock's States?
Asked Answered
B

2

13

The book Growing Object Oriented Software gives several examples in jMock where the state is made explicit without exposing it through an API. I really like this idea. Is there a way to do this in Mockito?

Here's one example from the book

public class SniperLauncherTest {
   private final States auctionState = context.states("auction state")
                                              .startsAs("not joined");

   @Test public void addsNewSniperToCollectorAndThenJoinsAuction() {
     final String itemId = "item 123";
     context.checking(new Expectations() {{
       allowing(auctionHouse).auctionFor(itemId); will(returnValue(auction));

       oneOf(sniperCollector).addSniper(with(sniperForItem(item)));
                                   when(auctionState.is("not joined"));      
       oneOf(auction).addAuctionEventListener(with(sniperForItem(itemId)));
                                   when(auctionState.is("not joined"));
       one(auction).join(); then(auctionState.is("joined"));
     }});

     launcher.joinAuction(itemId);
   }
}
Baldridge answered 3/7, 2011 at 22:38 Comment(0)
K
8

I used a spy for the self same exercise:

http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#13

I changed my SniperListener mock into a spy thus:

private final SniperListener sniperListenerSpy = spy(new SniperListenerStub());
private final AuctionSniper sniper = new AuctionSniper(auction, sniperListenerSpy);

And also created a stubbed implementation of SniperListener:

private class SniperListenerStub implements SniperListener {
    @Override
    public void sniperLost() {
    }

    @Override
    public void sniperBidding() {
        sniperState = SniperState.bidding;
    }

    @Override
    public void sniperWinning() {
    }
}

The book uses JMock's "States", but I used a nested enum instead:

private SniperState sniperState = SniperState.idle;

private enum SniperState {
    idle, winning, bidding
}

You then have to use regular JUnit asserts to test for the state:

@Test
public void reportsLostIfAuctionClosesWhenBidding() {
    sniper.currentPrice(123, 45, PriceSource.FromOtherBidder);
    sniper.auctionClosed();
    verify(sniperListenerSpy, atLeastOnce()).sniperLost();
    assertEquals(SniperState.bidding, sniperState);
}
Kb answered 26/2, 2014 at 16:44 Comment(3)
This way is cleaner than other answer. +1Polash
A lot better than the jMock used in the book (which is great, but has a few flaws). They constantly stress the need to make test code easy to grasp, but from that standpoint, judging from my newbie's perspective anyway, Mockito seems far superior.Lemur
However, SniperState is an unfortunate choice of name... because the book introduces its own SniperState class on p. 154 (and it's not a simple enum)...Lemur
J
7

Not that I'm aware of. I've used mockito a far amount and there's nothing in the doco similar to what I read on the JMock site about states. If I have it correctly they basically limit the time at which an exepection can occur to the duration of a specific state of another object. It's an interesting idea, but I'm struggling to see the applications for it.

In Mockito you can execute code using Stubbing with callbacks to do the same job. In the callback method you can execute further validations of the state. Alternatively you can employ a Custom argument matcher as they are also executed at the time of the call.

Both of these give you access to the code at execution time which is the time you want to check the state.

Jenijenica answered 3/7, 2011 at 23:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.