2016-04-02 8 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); 
} 

さて、私の2番目のテスト関数(userWriteDouble_checkIfItIsDouble_userTypedDouble)は失敗し、理由を見つけることができませんでした。ご覧のとおり、私は最初のテストと同じパターンを使いました。あなたの意見は何ですか?なぜこのテストは失敗しますか?いくつかの模擬フレームワーク(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

2番目のテストが失敗したと言っていますが、最初のテストは失敗しますか? –

答えて

1

だろう。これは初めて作成されたときにSystem.inへの参照を格納します。 2番目のテストでSystem.inを別の値に設定しても、ScannerSystem.inは変更されません。このようにクラスコードを変更すると、テストが修正されます。あなたは試験後System.inを復元する必要がありますところで

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

。私はという名前のライブラリを書いています。これは、System.inから読み取るコードのテストを書くことをさらに容易にします。

+0

ちょっと、ちょっと!あなたの答えをありがとう、私はそれをupvoted!さて、コードを変更しましたが、コンソールが入力を待つようになりました。 setIn()は私が与えた値を設定していないようです:\あなたの意見は何ですか?あなたの助けを前もってありがとう! – mirind4

+1

'UserInteractionService'を作成する前に' setIn'を呼び出さなければなりません。この順番でやっていますか? –

+0

魅力的な作品です!追加情報をありがとう! ;) – mirind4

2

。私はUserInteractionServiceにScannerをとるコンストラクタを与えることを検討します。私は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); 

のようになります。そして、あなたはあなたのテストで呼び出すサービスがScannerの静的フィールドを使用しないでください

new UserInteractionService (scanner) 
+1

ありがとう!さて、静的スキャナを持つ必要はありません。実際に私はMockitoを使っているので、これで解決しようとしています。私はMockitoとほとんど同じものを書く必要があると思うので、うまくいけば答えを受け入れるでしょう! ;) – mirind4

+0

aah私はMociktoでScannerクラスをモックできないので問題があります。 Mockitoでは、静的クラスまたは最終クラスを嘲笑することはできません。私は私の実装でBefferedReaderに変更すると思います – mirind4