在TDD開發中,也許我們會遇見對一些重要的無返回值的行為測試,比如在用戶的積分DB中增加用戶的積分,這個行為對於我們的業務具有重要的價值,所以我們也希望能測試覆蓋這部分業務價值。這個時候我們就得使用mockito帶來的verify斷言,但verify的參數斷言主要有eq,或者any常見的方式。有時我們也希望能夠斷言對象的一部分屬性,比如上文的積分數值,對於不同的場景增加的用戶積分可能不同。
回到Mockito的參數Matcher,Mockito給我們提供了ArgumentMatcher,以供我們來擴展Matcher。下面假設一個增加用戶積分的場景:
public class Game { private String type; private int rate; public Game(String type, int rate) { this.type = type; this.rate = rate; } public String getType() { return type; } public int getRate() { return rate; } } public class GameDao { public void addRate(Game game) { //TODO: insert to db } }
我們希望能夠對verify GameDao調用了addRate,並且是積分rate為特定值。
所以我們可以擴展Mockito的ArgumentMatcher:
public class PartyMatcher<T> extends ArgumentMatcher<T> { private Object value; private Function<T, Object> function; public PartyMatcher(Function<T, Object> getProperty, Object value) { this.value = value; this.function = getProperty; } public static <F> PartyMatcher<F> partyMatcher(Function<F, Object> getProperty, Object value) { return new PartyMatcher<F>(getProperty, value); } @Override public boolean matches(Object o) { return function.apply((T) o).equals(value); } }
所以我們的測試可以如下:
@Test public void should_run_customer_mockito_matcher() throws Exception { final GameDao gameDao = mock(GameDao.class); gameDao.addRate(new Game("簽到", 7)); verify(gameDao).addRate(argThat(new PartyMatcher<Game>(new Function<Game, Object>() { @Override public Object apply(Game game) { return game.getRate(); } }, 7))); verify(gameDao).addRate(argThat(new PartyMatcher<Game>(new Function<Game, Object>() { @Override public Object apply(Game game) { return game.getType(); } }, "簽到"))); }
Mockito給我們提供了很多關於Matcher擴展的方法,本文只是ArgumentMatcher的實例。