在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的實例。
