3

このメソッドの単体テストを作成するのは非常に難しいことがわかりました。基本的に、ユーザーがquitコマンドを入力するとプログラムが終了します。

SytemExitクラス:

public class SystemExit {
    public void exit(int status) {
        System.exit(status);
    }
}

私の静的メソッド:

public static void exitWhenQuitDetected() {
final SystemExit systemExit = new SystemExit();
final String QUIT = "quit";
String line = "";
try {
    final InputStreamReader input = new InputStreamReader(System.in);
    final BufferedReader in = new BufferedReader(input);
    while (!(line.equals(QUIT))) {
        line = in.readLine();
        if (line.equals(QUIT)) {
            System.out.println("You are now quiting the program");                  
            systemExit.exit(1);
        }
    }
} catch (Exception e) {
    System.err.println("Error: " + e.getMessage());
}
}   

メソッドexitWhenQuitDetectedをユニットテストするのに苦労しているので、ここでは何かが正しくありません(私はモックにMockitoを使用しています)。InputStreamReaderをモックして、終了が検出されたときにSystemExit.exitメソッドが呼び出されることを確認するにはどうすればよいですか?これに光を当てていただけませんか?ありがとう。

現在取り組んでいるテストを追加しましたが、機能していません。

    @Test
@Ignore
public void shouldExitProgramWhenTypeQuit() {
    String quit = "quit";           
    SystemExit systemExit = mock(SystemExit.class);
    try {
        BufferedReader bufferedReader = mock(BufferedReader.class);
        when(bufferedReader.readLine()).thenReturn(quit + "\n");
        SomeClass.exitWhenQuitDetected();
        verify(systemExit, times(1)).exit(1);
    } catch (IOException e) {           
        e.printStackTrace();
    }       
}
4

4 に答える 4

3

バニラ Mockito だけでなく、 PowerMockito Jars をプロジェクトに含める必要があります。Powermock ライブラリは、静的および/または最終的なクラスとメソッドをモックするために設計されています。

次のこのブログ投稿には、同様のシナリオを説明するサンプル コードが含まれています。

基本的に、これに似たテストクラスが必要です...

@RunWith(PowerMockRunner.class)
@PrepareForTest({System.class, ClassToTest.class})
public class SystemExitTest {

    @Test
    public void shouldCallSystemExit() {

        PowerMockito.mockStatic(System.class);

        ClassToTest.methodToTest();

        PowerMockito.verifyStatic();

        System.exit(0);

        System.out.println("If this message displays them System.exit() was mocked successfully");
    }    
}

この単純な実装クラスを考えると...

public class ClassToTest {

    public static void methodToTest() {
        // do some stuff
        System.exit(0);
    }
}
于 2012-09-02T19:26:13.753 に答える
1

SystemExitクラスを実行すると JVM が終了するため、実際にクラスをテストする方法はありません。SecurityManagerを検出して拒否する を使用して何かを実行できるかもしれませんがSystem.exit()、コードの 1 行をテストするには非常に多くの作業が必要になります。

あなたは正しいことをしました - 機能を小さなクラスにまとめました。私があなたなら、それにインターフェースを置き、インターフェースを介して解析コードに挿入します。次に、テストでモックを挿入し、解析コードがexit()正しい終了コードでモックのメソッドを呼び出すことをテストできます。

クラスのコードSystemExitは小さく、自己完結型であり、テストせずに見て推論するのに十分です.IMHO.

于 2012-09-02T08:58:54.230 に答える
1

独自のロジックを持たない別のクラスに実際の終了コードを配置することで、既に作業の 90% を完了しています。問題は、静的メソッドの使用が原因です。

exitWhenQuitDetected非静的にすることをお勧めします。必要なときにインスタンス化でき、モック化された で作成できるクラスに入れますSystemExit。このようなもの。

public class SomeClass{
  private final SystemExit exiter;
  private final static String QUIT = "quit";
  public SomeClass(){
    this(new SystemExit());
  }

  SomeClass(SystemExit exiter){
    this.exiter = exiter;
  }

  public static void exitWhenQuitDetected() {    
    String line = "";    
    try {    
      final InputStreamReader input = new InputStreamReader(System.in);    
      final BufferedReader in = new BufferedReader(input);    
      while (!(line.equals(QUIT))) {    
        line = in.readLine();    
        if (line.equals(QUIT)) {    
          System.out.println("You are now quiting the program");                      
          exiter.exit(1);    
        }    
      }    
    } catch (Exception e) {    
      System.err.println("Error: " + e.getMessage());    
    }    
  }       

  // ...
}

次に、テストで のモックを作成しSystemExit、の package-private コンストラクターをSomeClass使用して、モックを として使用するオブジェクトを作成できますexiter。その後、テストを実行verifyし、モックで実行できますSystemExit

于 2012-09-02T22:11:46.087 に答える
0

たくさんの技術的な解決策が提供されました。別の見方を指摘したいと思います。

このコードは、実際には単体テストされるべきではありません。

単体テストから得られる最大のメリットは、特に多くの分岐がある複雑なビジネスコードに単体テストを適用する場合です。

コードが些細なものである場合、それは単に十分に高い投資収益率を持っていないので、その周りに単体テストを書くことはお勧めしません。あなたのケースは実際に私の主張を悪化させます。このような単純なコードをテストし、それを利益と比較するのにかかる労力の量を考えてください。これは本当に努力する価値がありますか。これは本当にあなた自身のコードをもっと信頼するようになりますか?

于 2012-09-02T19:35:14.037 に答える