2013-05-06 17 views
7

私は本当にTDDに入っています。私はjUnitでmockitoを使用してコードをテストする能力を向上させました。私は本当にモッキートを愛しています!引数でクラスをインスタンス化せずにパラメータの静的メソッドを呼び出す

できるだけ共同作業者をメソッドに渡し、可能な限りコンストラクタで行われる作業を制限するなど、コーディングに関する考え方を変更する必要があることに気付きました。

次のシナリオでは、ここで専門家からのアドバイスが必要です。

私はメソッドを持っていますが、それは特定のクラスでいくつかの静的メソッドを呼び出すことになります。例えば。

public void method(){ 
    OtherClass.staticMethod(); 
} 

これは一般的には悪いですが、私のシナリオでは必要です。私のユニットテストでコードをよりテスト可能にするために、私はOtherClassへの依存を避けて引数として渡したいと思います。

コンパイル時にエラーが発生するため、これは機能しません。

public void method(Class<? extends OtherClass> util){ 
    util.staticMethod(); 
} 
... 
method(OtherClass.class); 

これは動作しますが、それは単にメソッドのような静的なユーティリティのクラスだと、私は、する必要がない場合、私はインスタンス化OtherClassが好きではない:あなたに

public void method(OtherClass util){ 
    util.staticMethod(); 
} 
... 
method(new OtherClass()); 

私の質問: 新しいキーワードを使用せずにこれを達成するより良い方法がありますか?あなたのコードサンプルで

+2

新しいユーザーのための非常に整形式の質問、おめでとうございます。 – MarioDS

+0

'OtherClass'のサブクラスのインスタンスを渡すと、あなたの最後のコードが単語になるかどうかわかりません。インスタンスを介して静的メソッドにアクセスすることは、**インスタンス**に関連していないため、混乱しているように思えます。 –

+0

ところで、あなたのケースでは静的メソッドの代わりに**シングルトンパターン**を使用しますか? –

答えて

0

は:

public void method(){ 
    OtherClass.staticMethod(); 
} 

私の理解であり、静的メソッドの呼び出しから上記以外の方法では、いくつかのロジックがあるはず、それはあなたが静的メソッドをテストしないようにしたいものです。

そのような場合は、OtherClass.staticMethodという模擬実装を作成して、すべてのロジックをバイパスしたり、希望の値を返したり、特定のロジックを実装したりすることができます。これにより、OtherClassの依存関係が回避され、テストによって明示的に制御されます。

0

あなたはこの

public void method(Class<? extends OtherClass> clazz) throws Exception { 
    Method[] mArray = clazz.getMethods(); 
    for(Method m :mArray) { 
     if(!m.isAccessible()) m.setAccessible(true); 
     if((m.getModifiers() & Modifier.STATIC) != 0) { // Here a method which is static is executed. You can change this condition, to suit your needs 
      m.invoke(null); 
     } 
    } 
} 

のようなあなたの方法を変更することによって、あなたの最初のアプローチを使用することができますし、そのクラスの新しいオブジェクトを通過することなく

method(OtherClass.class); 

を呼び出すことによって、それを呼び出すことができます

0

反射を使用できます:

// exceptions management omitted 
public void method(Class<? extends OtherClass> clazz, String methodName) { 
    // methodName could also be a constant if it won't change 
    clazz.getMethod(methodName).invoke(null); 
} 

次に、ここで

method(OtherClass.class, "staticMethod"); 
0

は、私はちょうどしようとしたものです:

public void testMethod(Class<T> clazz) throws Exception{   
     Method m = clazz.getMethod("staticMethod",null); 
     m.invoke(null,null); 
    } 

私は、静的メソッドは、引数を取らないことを(あなたの例で述べたように)を想定。

getMethod()およびinovke()の方法のドキュメントを参照してください。

0

ここにある静的コードのビットで何も間違って - それはグローバルな状態にアクセスしていない場合:

静的コードをすることができます

public void method(){ 
    OtherClass.staticMethod(); 
} 

純粋に手続き的である場合静的呼び出しをメソッド内で唯一の操作として保持している限り、method()の周りをモックします。

これ以外の静的メソッドでグローバル状態が保護される場合は、あなたはの世話をして試験時間でインスタンスTestRegistryを持つことができますので、あなたは、レジストリのサブクラスを作成することができシングルトン+ロケータ

public class Registry { 
    DoSomethingInterface getOtherClass() { 
     return OtherClass.getSingleton(); 
    } 
} 


public void method(Registry reg){ 
    reg.getOtherClass().doSomething(); 
} 

、getOtherClass()ロケータへの変化のすべての種類を提供するとしたほうが良いですクリーンなグローバル状態やその他のものを提供する

他のクラスが静的である必要がある場合は、それを変更することはできません。ライブラリクラス)、あなたはあなたのインターフェイスでそれをラップすることができます:これは働くだろう

public class Registry { 
    DoSomethingInterface getOtherClass() { 
     return new DoSomethingInterface(){ 
      public void doSomething() { 
       OtherClass.staticMethod(); 
      } 
     }; 
    } 
} 
1

が、私はしていない場合、それはもっぱらだと私は、インスタンス化OtherClassを好きではありませんメソッドのような静的なユーティリティクラス:

public void method(OtherClass util){ 
    util.staticMethod(); 
} 
... 
method(new OtherClass()); 

それは常にあなたがを渡した場合でも(関係なく、オブジェクトのあなたが合格、OtherClassからメソッドの実装を呼び出しますよう実は、これは、動作しません。)。

コンパイル時のチェックをバイパスする(コンパイラーが間違ったスペルのメソッド名を検出しない)ので、テストの簡略化のためだけにリフレクションを使用しないことを強くお勧めします。 、javadoc hovers、リファクタリングサポート、呼び出し階層表示、定義にジャンプ...)

一般的なアプローチは、多態性ディスパッチを使用することです。 Javaでは、メソッドが静的ではなくプライベートでないことが必要です。したがって、経験則は:モックが必要な場合は、静的であってはなりません。

オブジェクトインスタンスを最もよく取得する方法は、状況によって異なります。依存関係インジェクション(あなたのアプローチ)、リソースロケータパターン、およびシングルトンパターンにはそれぞれ長所と短所があります。

関連する問題