2013-03-24 26 views
11

JMockit 1.1を使用しています。私がやりたいことは、プライベートメソッドを呼び出して戻り値をテストすることだけです。しかし、私は正確にこれを行う方法を理解するのが難しいです、JMockit De-Encapsulationの例からです。JMockitでプライベートメソッドを呼び出して結果をテストする

私がテストしようとしているメソッドは、このクラスのプライベートメソッドです:

public class StringToTransaction { 
    private List<String> parseTransactionString(final String input) { 
     // .. processing 
     return resultList; 
    } 
} 

そして、私のテストコードは以下の通りです。

@Test 
public void testParsingForCommas() { 
    final StringToTransaction tested = new StringToTransaction(); 
    final List<String> expected = new ArrayList<String>(); 
    // Add expected strings list here.. 
    new Expectations() { 
     { 
     invoke(tested, "parseTransactionString", "blah blah"); 
     returns(expected); 
     } 
    }; 
} 

そして、私は取得していますエラーは次のとおりです。私はただの結果をテスト..私はクラスをモックとしたいとは思わないので、

java.lang.IllegalStateException: Missing invocation to mocked type at this point; please make sure such invocations appear only after the declaration of a suitable mock field or parameter

はおそらく、私は、ここでは全体のAPIを誤解していますプライベートメソッドを呼び出す

答えて

25

あなたはこれをあまりにも複雑にしていると思います。あなたはExpectationsブロックをまったく使用すべきではありません。実際は予想と同じであることを

基本的
@Test 
public void testParsingForCommas() { 
    StringToTransaction tested = new StringToTransaction(); 
    List<String> expected = new ArrayList<String>(); 
    // Add expected strings list here.. 

    List<String> actual = Deencapsulation.invoke(tested, "parseTransactionString", "blah blah"); 
    assertEquals(expected, actual); 
} 

、Deencapsulation経由でプライベートメソッドを呼び出してテスト:あなたがする必要があるのは、このようなものです。メソッドが公開されていればあなたのようになります。嘲笑は行われていないので、期待値ブロックは必要ありません。

+0

こんにちは@JeffOlson - そのクラスはどのinvoke()メソッドですか? Expectationsでは、invoke()は保護されたインスタンスメソッドです。あるいは、java.lang.reflect.Method.invoke()を使用してJMockitを完全に無視してください。 –

+0

最後に私は理解しています。それは 'Deencapsulation.invoke'です。@ JeffOlsonに感謝し、https://グループのRogerioに感謝します。 google.com/d/msg/jmockit-users/oEgjW0DfmgU/3pEE1mjt1ncJ –

+0

はい、正しいです。申し訳ありませんがもっと明確ではありませんが、最初の例では(おそらく静的インポートを介して) 'invoke()'を直接使用していたので、そのまま残しておくと思いました。私は、これを将来読むかもしれない誰かのために、私の答えをより明確にするように更新するつもりです。 –

0

なぜプライベートメソッドを直接テストしたいですか?ほとんどの時代のAPIメソッド、つまりパブリックインターフェイスメソッドはユニットテストされており、プライベートメソッドは間接的にと一緒にテストされます。 アサーション文は、パブリックメソッド内で呼び出すプライベートメソッドからの期待値を入力できます。したがって、アサートが失敗した場合は、プライベートメソッドに問題があると確信しています。したがって、個別にテストする必要はありません。

+0

こんにちは@Ankur、私はお詫び申し上げますが、私はこの状況(または私ができるかどうか)でJMockitを正しく使う方法を含む答えを探しています。なぜプライベートメソッドをテストすべきか、テストすべきではないのかを議論するつもりはない。私は、パブリックメソッドを介してアサーションを使用することは別の方法であることを理解していますが、これは私がここで解決しようとしているものではありません。 –

+0

これを見てください:http://stackoverflow.com/questions/5729973/jmockit-two-mocked-instances-of-the-same-type –

+0

私はちょっと高密度@Ankurかもしれませんが、私はどのように動くことができませんその解決策を私の問題に適用してください。 :) **テスト**の初期化の前に**期待値**ブロックを置くと、コンパイルエラーが発生します。**テスト済みの変数は**解決できません。 –

2

この時点では、JMockitを使用できるかどうかはわかりません。私のプライベートメソッドのテストは、普通の古いリフレクションで行うことができますが、私はJMockitについて学ぶためにこの演習を始めました(そして私のコードをテストします)。このためJMockitを使用できない場合は、代わりにリフレクションを使用する方法があります。

@Test 
public void testParsingForCommas() throws Exception { 
    StringToTransaction tested = new StringToTransaction(); 
    ArrayList<String> expected = new ArrayList<>(); 
    expected.add("Test"); 

    Method declaredMethod = 
     tested.getClass().getDeclaredMethod("parseTransactionString", 
       String.class); 
    declaredMethod.setAccessible(true); 
    Object actual = declaredMethod.invoke(tested, "blah blah"); 
    assertEquals(expected, actual); 
} 

setAccessible(true)への呼び出しは、ここで重要なのか、プライベートメソッドを呼び出すときにinvokeが爆破されます。

declaredMethod.setAccessible(true); 

しかし、あなたは本当にクールであるかを知りたいですか? setAccessible(true)に電話をしないと、java.lang.StackOverflowErrorで爆発します! :)

関連する問題