使用系统规则测试System.in和System.out
編寫單元測(cè)試是軟件開(kāi)發(fā)的組成部分。 當(dāng)您的被測(cè)類與操作系統(tǒng)交互時(shí),您必須解決的一個(gè)問(wèn)題是模擬其行為。 這可以通過(guò)使用模擬代替Java Runtime Environment(JRE)提供的實(shí)際對(duì)象來(lái)完成。 支持Java的模擬的庫(kù)是例如嘲笑或jMock 。
當(dāng)您完全控制對(duì)象的實(shí)例化時(shí),模擬對(duì)象是一件好事。 在處理標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出時(shí),這有點(diǎn)棘手,但并非不可能,因?yàn)閖ava.lang.System允許您替換標(biāo)準(zhǔn)InputStream和OutputStream 。
為了不必在每個(gè)測(cè)試用例前后都手動(dòng)替換流,可以使用org.junit.rules.ExternalResource 。 此類提供了兩個(gè)方法before()和after() ,就像它們的名稱所暗示的那樣,在每個(gè)測(cè)試用例之前和之后調(diào)用。 這樣,您可以輕松地設(shè)置和清除一類中所有測(cè)試所需的資源。 或者,回到原始問(wèn)題,替換java.lang.System的輸入和輸出流。
我上面所描述的完全由庫(kù)system-rules實(shí)現(xiàn) 。 要查看其工作原理,讓我們從一個(gè)簡(jiǎn)單的示例開(kāi)始:
public class CliExample {private Scanner scanner = new Scanner(System.in, "UTF-8");public static void main(String[] args) {CliExample cliExample = new CliExample();cliExample.run();}private void run() {try {int a = readInNumber();int b = readInNumber();int sum = a + b;System.out.println(sum);} catch (InputMismatchException e) {System.err.println("The input is not a valid integer.");} catch (IOException e) {System.err.println("An input/output error occurred: " + e.getMessage());}}private int readInNumber() throws IOException {System.out.println("Please enter a number:");String nextInput = scanner.next();try {return Integer.valueOf(nextInput);} catch(Exception e) {throw new InputMismatchException();}} }上面的代碼從標(biāo)準(zhǔn)輸入中讀取兩個(gè)整數(shù),并打印出其總和。 如果用戶提供了無(wú)效的輸入,則程序應(yīng)在錯(cuò)誤流上輸出適當(dāng)?shù)南ⅰ?
在第一個(gè)測(cè)試用例中,我們要驗(yàn)證程序是否正確地將兩個(gè)數(shù)字求和并打印出結(jié)果:
public class CliExampleTest {@Rulepublic final StandardErrorStreamLog stdErrLog = new StandardErrorStreamLog();@Rulepublic final StandardOutputStreamLog stdOutLog = new StandardOutputStreamLog();@Rulepublic final TextFromStandardInputStream systemInMock = emptyStandardInputStream();@Testpublic void testSuccessfulExecution() {systemInMock.provideText("2\n3\n");CliExample.main(new String[]{});assertThat(stdOutLog.getLog(), is("Please enter a number:\r\nPlease enter a number:\r\n5\r\n"));}... }為了模擬System.in我們利用系統(tǒng)規(guī)則的TextFromStandardInputStream 。 通過(guò)調(diào)用emptyStandardInputStream()用一個(gè)空的輸入流初始化實(shí)例變量。 在測(cè)試用例本身中,我們通過(guò)在適當(dāng)?shù)奈恢谜{(diào)用帶有換行符的provideText()來(lái)為應(yīng)用程序提供信息。 然后,我們調(diào)用應(yīng)用程序的main()方法。 最后,我們必須斷言該應(yīng)用程序已將兩個(gè)輸入語(yǔ)句和結(jié)果寫入標(biāo)準(zhǔn)輸入。 后者是通過(guò)StandardOutputStreamLog實(shí)例完成的。 通過(guò)調(diào)用其方法getLog()我們可以檢索在當(dāng)前測(cè)試用例中已寫入標(biāo)準(zhǔn)輸出的所有內(nèi)容。
StandardErrorStreamLog可以類似地用于驗(yàn)證寫入標(biāo)準(zhǔn)錯(cuò)誤的內(nèi)容:
@Test public void testInvalidInput() throws IOException {systemInMock.provideText("a\n");CliExample.main(new String[]{});assertThat(stdErrLog.getLog(), is("The input is not a valid integer.\r\n")); }除此之外, system-rules還提供了使用System.getProperty() , System.setProperty() , System.exit()和System.getSecurityManager() 。
結(jié)論 :通過(guò)系統(tǒng)規(guī)則測(cè)試,帶有單元測(cè)試的命令行應(yīng)用程序比使用junit的規(guī)則本身更加簡(jiǎn)單。 每個(gè)測(cè)試用例前后的所有樣板代碼都在一些易于使用的規(guī)則之內(nèi),用于更新系統(tǒng)環(huán)境。
PS:您可以在此處找到完整的資源。
翻譯自: https://www.javacodegeeks.com/2015/01/testing-system-in-and-system-out-with-system-rules.html
總結(jié)
以上是生活随笔為你收集整理的使用系统规则测试System.in和System.out的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 意大利人口和面积 关于意大利人口和面积介
- 下一篇: Windows上的Oracle Java