18

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

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

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:この時点でモックされたタイプへの呼び出しがありません。このような呼び出しは、適切なモックフィールドまたはパラメータの宣言後にのみ表示されることを確認してください

クラスをモックしたくないので、おそらくここでAPI全体を誤解しました。プライベートメソッドを呼び出した結果をテストするだけです。

4

6 に答える 6

39

あなたはこれを複雑にしすぎていると思います。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);
}

基本的に、カプセル化解除を介してプライベートメソッドを呼び出し、実際が期待値と等しいことをテストします。メソッドが公開されている場合と同じように。モックは行われていないため、Expectationsブロックは必要ありません。

于 2013-03-25T05:23:11.353 に答える
3

現時点では、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:)

于 2013-03-25T09:56:57.870 に答える
1

最新のJmockitではプライベートメソッドのモックは許可されていません。プライベートメソッドをモックする代わりに、回避策としてそのプライベートメソッド内で使用されるAPIをモックすることができます。

この回避策は、最終的な解決策として扱うこともできます。

例:
実際のクラス:

class A {

  private int getId(String name){  //private method
      return DAOManager.getDao().getId(name);  //Call to non-private method can be mocked.
  }
}  

テストクラス:

public class ATest{

  @Before
  public void setUp(){
    new MockDAOManager();
  }

  //Mock APIs used by the private method `getId`.
  public static class MockDAOManager extends MockUp<MockDAOManager>{
     static mocked_user_id = 101;

     @Mock
     public DAOManager getDao() throws Exception{
          return new DAOManager();
     }

     @Mock
     public Integer getId(String name){
         return mocked_user_id;
     }
  }
}

ノート:

  • そのようなロジック(プライベートメソッドが別の非プライベートメソッドを呼び出す)がない場合は、コードをリファクタリングする必要があります。そうしないと、これは機能しません。
  • DAOManager.getDao().getId(name)これはプライベートAPIではありません。
  • そのプライベートメソッドで使用されるすべてのAPIをモックする必要があるかもしれません。
于 2021-05-25T02:46:23.577 に答える
0

1.35(?)から開始jmockitはそのヘルパーメソッドを削除しました。それがもはや役に立たないという理由で(私は完全には理解していません)

しかし、はい、このユーティリティは他の場所で利用できます

org.springframework.test.util.ReflectionTestUtils
于 2018-10-17T01:58:54.010 に答える
0

@Jeff Olsonが述べたように、Beanを宣言することでBeanのプライベートメソッドを呼び出すこともできます@Tested

次に例を示します。

// Java

    @Tested
    private YourServiceImplClass serviceImpl;

    @Test
    public void testPrivateMethod() {
   
          List<String> expected = new ArrayList<String>();
          // Add expected strings list here..

          List<String> actual = Deencapsulation.invoke(serviceImpl, "yourPrivateMethod", "arguments");
          assertEquals(expected, actual);
    }
于 2018-11-30T18:19:32.663 に答える
-2

なぜプライベートメソッドを直接テストしたいのですか?ほとんどの場合、APIメソッド、つまりパブリックインターフェイスメソッドはユニットテストされます。プライベートメソッドもそれらと一緒に間接的にテストされるためです。パブリックメソッド内で呼び出すプライベートメソッドからの期待値を使用してassertステートメントを配置できます。したがって、assertが失敗した場合は、プライベートメソッドに問題があることを確認してください。したがって、個別にテストする必要はありません。

于 2013-03-24T06:23:54.913 に答える