2016-04-02 69 views
0

首先,我嘗試在這個很酷的站點尋找一些解決方案。我發現了一個與我的問題有關的問題,但是我的測試仍然失敗。 我發現的問題,可以在這裏找到:JUnit testing with simulated user input使用JUnit測試函數,其中函數獲取用戶輸入

讓我們來看看我的實現:

我有讀,然後驗證用戶輸入的用戶交互服務類:UserInteractionService.java

package Services; 

import java.util.Scanner; 

public class UserInteractionService { 

    private static Scanner scanner = new Scanner(System.in); 

    public static int readIntegerAndValidate() { 
     while (!scanner.hasNextInt()) { 
      System.out.println("It is not a valid integer number. Try again!"); 
      scanner.next(); 
     } 
     return scanner.nextInt(); 

    } 

    public static double readDoubleAndValidate() { 
     while (!scanner.hasNextDouble()) { 
      System.out.println("It is not a valid number. Try again!"); 
      scanner.next(); 
     } 
     return scanner.nextDouble(); 
    } 
} 

當然,我有這個服務類的測試類:UserInteractionServiceTest.java

@Test 
public void userWriteInput_checkIfItIsInteger_userTypedInteger() { 
    String inputData = "5"; 
    System.setIn(new ByteArrayInputStream(inputData.getBytes())); 
    int input = readIntegerAndValidate(); 
    assertEquals(5, input); 
} 

@Test 
public void userWriteDouble_checkIfItIsDouble_userTypedDouble() { 
    String inputData = "5.3"; 
    System.setIn(new ByteArrayInputStream(inputData.getBytes())); 
    double input = readDoubleAndValidate(); 
    assertEquals(5.3, input, 0); 
} 

那麼,我的第二個測試函數(userWriteDouble_checkIfItIsDouble_userTypedDouble)失敗了,我無法找到原因...正如您所看到的,我使用了與de第一次測試中相同的模式。你有什麼看法,爲什麼這個測試失敗?我應該使用一些模擬框架(Mockito)嗎?預先感謝您的答案!

故障跟蹤:

java.util.NoSuchElementException 
    at java.util.Scanner.throwFor(Unknown Source) 
    at java.util.Scanner.next(Unknown Source) 
    at Services.UserInteractionService.readDoubleAndValidate(UserInteractionService.java:21) 
    at Services.UserInteractionServiceTest.userWriteDouble_checkIfItIsDouble_userTypedDouble(UserInteractionServiceTest.java:23) 
... 
+0

我通常會嘲笑掃描儀,是的。什麼是測試失敗輸出? – Willcodeforfun

+0

@Willcodeforfun感謝您的評論!我用失敗追蹤編輯了我的答案。所以你說嘲笑掃描儀是個好主意。解決方案如何? – mirind4

+0

你說第二次測試失敗了,第一次測試通過了嗎? –

回答

1

不要使用靜態字段的Scanner。它在第一次創建時存儲對System.in的引用。在第二個測試中再次將System.in設置爲不同的值不會更改ScannerSystem.in。像這樣改變你的班級代碼可以修復你的測試。

private Scanner scanner = new Scanner(System.in); 

順便說一句,你應該在測試後恢復System.in。我編寫了一個名爲System Rules的庫,可以更輕鬆地爲從System.in讀取的代碼編寫測試。

+0

嘿!感謝您的回答,我向上投票!好吧,我已經更改了代碼,但現在控制檯等待我的輸入。看來setIn()並沒有給我賦予的值:\你的意見是什麼?在此先感謝您的幫助! – mirind4

+1

您必須在創建UserInteractionService之前調用'setIn'。你是按照這個順序嗎? –

+0

工程就像一個魅力!感謝您的附加信息! ;) – mirind4

2

找到了更難通過使掃描儀的靜態測試代碼。我會考慮給UserInteractionService一個帶掃描器的構造函數。我建議EasyMock的和測試的代碼看起來像

import static org.easymock.EasyMock.*; 

Scanner scanner = createMock(Scanner.class); 
expect(scanner.hasNextDouble()).and return(true).once(); 
expect(scanner.nextDouble()).and return(5.3).once(); 

replay(scanner); 

你在測試中調用該服務將是一個

new UserInteractionService (scanner) 
+1

謝謝!那麼,沒有必要有一個靜態掃描儀。其實我使用Mockito,所以我嘗試用它來解決它。我認爲我必須寫與Mockito幾乎相同的,所以如果它有效,我會接受你的答案! ;) – mirind4

+0

啊我有問題,因爲我不能用Mocikto模擬Scanner類。通過Mockito,靜態或最終的類不能被嘲笑。我想我會在我的執行中更改爲BefferedReader – mirind4