Michael Deardeuff
Michael Deardeuff

Reputation: 10707

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

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);
   }
}

Upvotes: 13

Views: 1555

Answers (2)

drekka
drekka

Reputation: 21893

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.

Upvotes: 7

ayahuasca
ayahuasca

Reputation: 555

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);
}

Upvotes: 8

Related Questions