如何测试System.out.println();通过嘲弄

时间:2015-11-06 15:15:57

标签: java unit-testing mockito

你好我必须练习如何使用Mockito有人请告诉我如何使用模拟对象来测试基于控制台的输出测试,例如

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();

2 个答案:

答案 0 :(得分:4)

首先关闭 - 调用System.exit()会破坏您的测试。

第二 - 模仿System类不是一个好主意。将System.out重定向到伪造或存根更有意义。

第三 - 从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!"));
    }

}

答案 1 :(得分:2)

我不会使用mockito来测试这个。我将System.out(通过System.setOut)设置为ByteArrayOutputStream支持的PrintStream并检查。

如果你想进行单元测试,你也想摆脱那个System.exit。

我要嘲笑的两件事是RandomScanner。我还要考虑将逻辑从显示中分离出来。你并不关心输出什么,但是逻辑理解输入X你会得到输出Y.

为什么呢?如果您模拟System.out(您可以通过System.setOut执行),您最终会显示您可以编写模拟验证但很少。测试代码最终会非常脆弱,很难遵循。 通过使用ByteArrayOutputStream,您可以以显着简化的方式获得输出。

随机和扫描程序是对stub out更简单的外部系统,不会给你留下那么脆弱的代码。

然而,正如我所说,我将游戏逻辑与用户输入分开。例如,我有一个理解游戏的课程。

class Game
   // implementation
   Game(int startingNumber, int attemptsAllowed);

   public {WON,HIGHER,LOWER,LOST} go(int guess) { ... }
}

然后可以轻松地测试此对象,并与(难以测试)用户界面完全隔离。

当您想要测试用户界面时,您可以模拟此对象以确保它始终返回您想要返回的内容。