你好,我必须练习如何使用Mockito,有人能告诉我我们如何使用mock对象来测试基于控制台的输出测试吗?例如
Random rand = new Random();
int number = 1+rand.nextInt(100); // random number 1 to 100
Scanner scan = new Scanner(System.in);
for (int i=1; i<=10; i++){ // for loop from 1 to 10
System.out.println(" guess "+i+ ":");``
int guess = scan.nextInt();
//if guess is greater than number entered
if(guess>number)
System.out.println("Clue: lower");
//if guess is less than number entered
else if (guess<number )
System.out.println("lue: Higher");
//if guess is equal than number entered
else if(guess==number) {
System.out.println("Correct answer after only "+ i + " guesses – Excellent!");
scan.close();
System.exit(-1);
}
}
System.out.println("you lost" + number);
scan.close();
首先,对System.exit()的调用将破坏您的测试。
第二,嘲笑System
类不是一个好主意。将System.out重定向到false或stub更有意义。
第三,从System.in中读取内容在测试中也很难做到。
除此之外:为了可读性,我还随意减少了代码:
public class WritesOut {
public static void doIt() {
System.out.println("did it!");
}
}
测试应测试Line是否打印到System.out:
import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.junit.Test;
public class WritesOutTestUsingStub {
@Test
public void testDoIt() throws Exception {
//Redirect System.out to buffer
ByteArrayOutputStream bo = new ByteArrayOutputStream();
System.setOut(new PrintStream(bo));
MockOut.doIt();
bo.flush();
String allWrittenLines = new String(bo.toByteArray());
assertTrue(allWrittenLines.contains("did it!"));
}
}
我不会使用mockito来测试它。我会将System.out(通过System.setOut)设置为ByteArrayOutputStream支持的PrintStream并进行检查。
如果你想进行单元测试,你还需要去掉那个System.exit。
我会嘲笑的两件事是随机和扫描仪。我也会考虑将逻辑与显示分离。你并不真正关心输出什么,而是逻辑理解输入X会得到输出Y。
为什么?如果您模拟System.out(您可以通过System.setOut进行),您最终会显示您可以编写模拟验证,但几乎没有其他内容。测试代码最终会变得非常脆弱,并且很难遵循。通过使用ByteArrayOutputStream,您可以以显著简化的方式获得输出。
Random和Scanner是外部系统,它们更容易截取,不会给你留下太脆弱的代码。
然而,正如我所说,我将把游戏逻辑与用户输入分开。例如,我会有一个理解游戏的班级。
class Game
// implementation
Game(int startingNumber, int attemptsAllowed);
public {WON,HIGHER,LOWER,LOST} go(int guess) { ... }
}
然后,这个对象可以很容易地进行测试,并且与(更难测试的)用户界面完全隔离。
当你想测试用户界面时,你可以模拟这个对象,以确保它总是返回你想要的东西。