测试桩Stub
桩:截断的或非常短的物体。
测试桩,用最简单的可能实现代替Real。
基本实现:所有方法仅一行,返回默认值。
public class LoggerStub implements Logger {
public void log(LogLevel level, String message) {
// still a no-op
}
public LogLevel getLogLevel() {
return LogLevel.WARN; // hard-coded return value
}
}
伪造对象Fake
Fake是Real的简化版本,但是没有副作用。
public interface UserRepository {
void save(User user);
User findById(long id);
User findByUsername(String username);
}
public class FakeUserRepository implements UserRepository {
private Collection<User> users = new ArrayList<User>();
public void save(User user) {
if(findById(user.getId()) == null) {
users.add(user);
}
}
public User findById(long id) {
for(User user : users) {
if(user.getId() == id) {
return user;
}
}
return null;
}
public User findByUsername(String username) {
for(User user : users) {
if(user.getUsername().equals(username)) {
return user;
}
}
return null;
}
}
测试间谍Spy
Spy是一种测试替身,它用于记录过去发生的情况,测试事后知道所发生的一切。
public class DLog {
private final DLogTarget[] targets;
public DLog(DLogTarget... targets) {
this.targets = targets;
}
public void write(Level level, String message) {
for(DLogTarget each : targets) {
each.write(level, message);
}
}
}
public class DLogTest {
@Test
public void writesEachMessageToAllTargets() {
SpyTarget spy1 = new SpyTarget();
SpyTarget spy2 = new SpyTarget();
DLog log = new DLog(spy1, spy2);
log.write(Level.INFO, "Hello world.");
assertTrue(spy1.received(Level.INFO, "Hello world."));
assertTrue(spy2.received(Level.INFO, "Hello world."));
}
}
// 使用SpyTarget跟踪数据
class SpyTarget implements DLogTarget {
private List<String> log = new ArrayList<String>();
public void write(Level level, String message) {
log.add(concatenated(level, message));
}
public boolean received(Level level, String message) {
return log.contains(concatenated(level, message));
}
private String concatenated(Level level, String message) {
return level.getName() + ":" + message;
}
}
模拟对象Mock
Mock是特殊的Spy。它是一个在特定情景下可配置行为的对象。