本书不断增长的面向对象软件在jMock中提供了几个示例,其中状态是明确的,而不通过API公开它。我真的喜欢这个主意。有没有办法在Mockito做到这一点?
这是书中的一个例子
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);
}
}
答案 0 :(得分:7)
不是我知道的。我已经使用了很多的模拟,并且doco中的任何内容都与我在JMock网站上关于状态的内容类似。如果我有正确的话,它们基本上限制了对另一个对象的特定状态的持续时间进行检测的时间。这是一个有趣的想法,但我很难看到它的应用程序。
在Mockito中,您可以使用Stubbing with callbacks执行相同的工作。在回调方法中,您可以执行状态的进一步验证。或者,您可以使用Custom argument matcher,因为它们也会在通话时执行。
这两个都允许您在执行时访问代码,这是您要检查状态的时间。
答案 1 :(得分:7)
我使用间谍进行同样的练习:
http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#13
我将我的SniperListener模拟器变成了间谍:
private final SniperListener sniperListenerSpy = spy(new SniperListenerStub());
private final AuctionSniper sniper = new AuctionSniper(auction, sniperListenerSpy);
还创建了SniperListener的存根实现:
private class SniperListenerStub implements SniperListener {
@Override
public void sniperLost() {
}
@Override
public void sniperBidding() {
sniperState = SniperState.bidding;
}
@Override
public void sniperWinning() {
}
}
这本书使用了JMock的“States”,但我使用了嵌套枚举:
private SniperState sniperState = SniperState.idle;
private enum SniperState {
idle, winning, bidding
}
然后,您必须使用常规JUnit断言来测试状态:
@Test
public void reportsLostIfAuctionClosesWhenBidding() {
sniper.currentPrice(123, 45, PriceSource.FromOtherBidder);
sniper.auctionClosed();
verify(sniperListenerSpy, atLeastOnce()).sniperLost();
assertEquals(SniperState.bidding, sniperState);
}