2016-06-22 15 views
2

リフレクションを使用してプライベート内部クラスのメソッドをテストする方法はありますか?以下のコードで は、どのように我々はあなたがMockitoを使ってモックオブジェクトを使用してこれをテストすることができFUNC-1およびFUNC-2内部プライベートクラスのテストメソッドへのリフレクションの使用

public class Outer extends AbstractOuter { 
private final Properties properties; 

public Outer(Properties properties) { 
    this.properties = properties; 
} 

private class Inner extends AbstractInner { 

    private int numOfProperties; 

    @Override 
    void func-1() throws Exception { 
     // 
    } 

    private int func-2(long l) { 
     // 
    } 
} 
} 
+2

"テストの動作、実装ではありません"。これがプライベート内部クラスの場合は、実装の詳細です。クラスの動作(パブリックメソッドを介して公開されている)について考え、それらをテストします。 –

+0

この実装の詳細をテストする必要があります。これは単体テストです。 – user1918858

+1

@ JaroslawPawlakのコメントと同様に、特定の動作が最もよくテストされている場合は、この動作をテスト可能なパブリックメソッドを持つ別のオブジェクトにリファクタリングすることを検討してください。これらのプライベートメソッドを持つ既存のオブジェクトは、内部的にテストされたパブリックビヘイビアでこの新しいオブジェクトを使用できます。 – FishStix

答えて

1
package SalesUnitsIntoCarton.mySolution; 

import java.lang.reflect.Field; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 

public class UtilityReflections { 
    private static final Object[] EMPTY = {}; 

    /** 
    * This method returns a value, returned by the method of a private inner class, of a given object instance. 
    * 
    * @param outerClassInstance This parameter needs to be an instance of the outer class that contains the private inner class. 
    * @param attributeNameOfInnerClassInOuterClass This is the name of the attribute that is an inner class type, within the outer class. 
    * @param innerClassName This is the class name of the inner class. 
    * @param methodNameOfInnerClass This is the name of the method inside the inner class that should be called. 
    * @return Returns the value returned by the method of the inner class. CAUTION: needs casting since its of type {@link Object} 
    * 
    * @throws SecurityException 
    * @throws NoSuchFieldException 
    * @throws ClassNotFoundException 
    * @throws NoSuchMethodException 
    * @throws InvocationTargetException 
    * @throws IllegalArgumentException 
    * @throws IllegalAccessException 
    * @throws Exception 
    */ 
    public static <T extends Object> Object executeInnerClassMethod(T outerClassInstance, String attributeNameOfInnerClassInOuterClass, String innerClassName, String methodNameOfInnerClass) 
     throws NoSuchFieldException, SecurityException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, 
     IllegalArgumentException, InvocationTargetException { 

     final Class<?> outerClass = outerClassInstance.getClass(); 

     final Field field = outerClass.getDeclaredField(attributeNameOfInnerClassInOuterClass); 
     field.setAccessible(true); 

     Class<?> innerClass = Class.forName(innerClassName); 
     innerClass = field.getType(); 

     //access the method 
     final Method method = innerClass.getDeclaredMethod(methodName, new Class<?>[]{}); 
     method.setAccessible(true); 
     return method.invoke(field.get(outerClassInstance), EMPTY); 
    } 
} 
-2

をテストすることができます。

+0

あなたはMockitoの使い方の詳細を教えてください。 – user1918858

+0

私はMockitoのウェブサイトに行きます。これも例を示しています –

0

何とか反射してsetAccessible(true)を使用しても可能ですが、特にプライベート非静的内部クラスがある場合は難しくなります。

最も興味深い質問は:どうしてそんなことをしたいのですか?

これらの内部クラスおよびメソッドは、テストされた外部クラスの動作に影響を与える必要があります。そのクラスをテストしてください!

クラスのプライベートな部分をテストしようとすると、設定が少なくて済み、テストなしのレガシーコードがあり、だけをテストしたいので、ほとんどの場合遅延テストが必要です。しかし、申し訳ありませんが、それは役に立たないです。

  • テストは、ホワイトボックス実装に結合した試験ではなく、全体的な動作は
  • 、最も重要なを変更しない場合でも、任意の内側のリファクタリングは、テストを壊すことがあり、クラス
  • のAPIです:内部クラスまたはプライベートメソッドが正しい方法で(またはまったく)使用されているかどうかはテストしません。

これを行うための全努力は役に立たず、代わりにフルクラスをテストしてください!

0

私はこれを処理する必要はありませんでしたが、私は良い質問だと思います。 私はこれについて100%確信していませんが、これはうまくいくかもしれません。

 Outer.class.getDeclaredClasses()[0].getDeclaredMethod("func-1").invoke(null); 

私は現在それをテストする環境がありません。しかし、おそらくそれは助けます。

関連する問題