4

入力引数として GenericFile を取得し、データを読み取り、追加の処理を行うクラスがあります。私はそれをテストする必要があります:

public class RealCardParser {

    public static final Logger l = LoggerFactory.getLogger(RealCardParser.class);

    @Handler
    public ArrayList<String> handle(GenericFile genericFile) throws IOException {
        ArrayList<String> strings = new ArrayList<String>();
        FileInputStream fstream = new FileInputStream((File) genericFile.getFile());
        DataInputStream in = new DataInputStream(fstream);
        BufferedReader br =  new BufferedReader(new InputStreamReader(in));
        String strLine = br.readLine();//skip header
        while ((strLine = br.readLine()) != null) {
            l.info("handling in parser: {}", strLine);
            strings.add(strLine);
        }
        br.close();
        return strings;
    }
}

問題は、新しい FileInputStream にあります。GenericFile をモックできますが、 FileInputStream がファイルが存在するかどうかをチェックするため、役に立ちません。クラスを次のように変更しました。

public class RealCardParser {

    public static final Logger l = LoggerFactory.getLogger(RealCardParser.class);

    protected BufferedReader getBufferedReader(GenericFile genericFile) throws FileNotFoundException {
        FileInputStream fstream = new FileInputStream((File) genericFile.getFile());
        DataInputStream in = new DataInputStream(fstream);
        return new BufferedReader(new InputStreamReader(in));
    }

    @Handler
    public ArrayList<String> handle(GenericFile genericFile) throws IOException {
        ArrayList<String> strings = new ArrayList<String>();
        BufferedReader br = getBufferedReader(genericFile);
        String strLine = br.readLine();//skip header
        while ((strLine = br.readLine()) != null) {
            l.info("handling in parser: {}", strLine);
            strings.add(strLine);
        }
        br.close();
        return strings;
    }
}

これで getBufferedReader メソッドをオーバーライドし、メソッド ハンドラをテストできます。

@RunWith(MockitoJUnitRunner.class)
public class RealCardParserTest {

    RealCardParser parser;

    @Mock
    GenericFile genericFile;

    @Mock
    BufferedReader bufferedReader;

    @Mock
    File file;

    @Before
    public void setUp() throws Exception {
        parser = new RealCardParser() {
            @Override
            public BufferedReader getBufferedReader(GenericFile genericFile) throws FileNotFoundException {
                return bufferedReader;
            }
        };

        when(genericFile.getFile()).thenReturn(file);
        when(bufferedReader.readLine()).thenReturn("header").thenReturn("1,2,3").thenReturn(null);
    }

    @Test
    public void testParser() throws Exception {
        parser.handle(genericFile);
        //do some asserts
    }
}

Handler メソッドは現在テストでカバーされていますが、cobertura の問題を引き起こすメソッド getBufferedReader はまだ発見されています。メソッド getBufferedReader をテストする方法、または問題の別の解決策があるかもしれませんか?

4

5 に答える 5

3

PowerMockRunner と PowerMockito を使用して FileInputStream をモックできます。モックについては、以下のコードを参照してください-

@RunWith(PowerMockRunner.class)
@PrepareForTest({
        FileInputStream.class
})
public class A{

 @Test
        public void testFileInputStream ()
                    throws Exception
       {
           final FileInputStream fileInputStreamMock = PowerMockito.mock(FileInputStream.class);
           PowerMockito.whenNew(FileInputStream.class).withArguments(Matchers.anyString())
                               .thenReturn(fileInputStreamMock);
    //Call the actual method containing the new constructor of FileInputStream 

        }
}
于 2013-07-30T10:48:12.337 に答える
2

まず、Streamの作成を依存関係に抽出します。したがって、RealCardParserは依存関係としてStreamSourceを取得します。

今、あなたはあなたの問題をアパートに持って行くことができます:

  1. 現在のテストでは、文字列から構築されたストリームを返すモック(またはこの場合は偽物)の実装を提供します。

  2. 実際のStreamSourceを実際のファイルでテストし、正しいコンテンツが返されるかどうかを確認します。

于 2012-09-26T07:06:35.977 に答える
2

これは悪い考えかもしれませんが、私の最初のアプローチは、ストリームオブジェクトをモックするのではなく、実際のテストファイルを作成することでした。

これはメソッドGenericFileではなくクラスをテストすると主張することができます。getBufferedReader

GenericFileおそらく許容できる方法は、テストのためにモックを介して実際に存在するテストファイルを返すことgetBufferedReaderです。

于 2012-09-26T06:54:08.477 に答える
2

これがあなたが望む答えではないことはわかっています。

単体テストの目的は、ロジックが正しいことを確認することです。単体テストは、正しくないロジックが記述されているバグをキャッチします。メソッドにロジックが含まれていない (つまり、分岐、ループ、または例外処理がない) 場合、そのメソッドを単体テストするのは経済的ではありません。つまり、単体テストにはお金がかかるということです。それを書く時間と、それを維持する時間です。ほとんどの単体テストは、バグを発見するか、テスト対象のドメインにバグがないことを再保証することで、その投資に対する見返りを提供します。

しかし、あなたのメソッドの単体テストgetBufferedReaderは、私たちの投資に対する見返りにはなりません。コストは有限ですが、失敗する可能性のある実際のロジックがないため、メリットはありません。したがって、そのような単体テストを作成しないでください。Cobertura の設定または組織の標準でそのような単体テストの存在が必要な場合、それらの設定または標準は間違っているため、変更する必要があります。そうでなければ、あなたの雇用主のお金は、無限の費用対利益比を持つ何かに費やされています.

分岐、ループ、または例外処理を含むメソッドの単体テストのみを記述するように、標準を変更することを強くお勧めします。

于 2012-09-26T19:31:10.540 に答える