2016-06-28 18 views
3

抽象クラスを模擬しようとしていますが、私が見たものからは可能ではないと思います。特定の抽象クラスを拡張する必要があるジェネリックスを使用するクラスがいくつかあります。彼らのグループ全体があり、成功裏に嘲笑されています。抽象クラスを抽象クラスで模擬しています

public abstract class ChildPresenter <T extends ChildView> { 
    private T view; 

    public abstract T getView(); 
} 

我々がテストしているクラスがそれに次があります:抽象クラスは、ジェネリックを返すを扱うとこのようになります一つの方法があるコンストラクタで

public class ParentPresenter { 
    private ConcreteChildPresenter1 childPresenter1; 
    private ConcreteChildPresenter2 childPresenter2; 
    private ConcreteChildPresenter3 childPresenter3; 
    private ConcreteChildPresenter4 childPresenter4; 
    List<ChildPresenter> childPresenters; 
} 

を、これらのクラスが注入され、 Google Guiceを使用して変数に設定し、子プレゼンターのリストに追加しました。

childPresentersオブジェクトをすべて反復し、メソッドgetView()を実行するものです。

私は私のテストクラスでこのようにそれを実行しようとしました:

public class ParentPresenterTest { 
    private ConcreteChildPresenter1 childPresenter1; 
    private ConcreteChildPresenter2 childPresenter2; 
    private ConcreteChildPresenter3 childPresenter3; 
    private ConcreteChildPresenter4 childPresenter4; 
    private List<ChildPresenter> childPresenters; 

    //This is an abstract class 
    private ChildView childView; 

    @BeforeTest 
    public void createInjector() { 
     Guice.createInjector(...//Creates a fake module and does binding for the variables mentioned earlier 
      //e.g. 
      childPresenter1 = mock(ConcreteChildPresenter1.class); 
      binder.bind(ConcreteChildPresenter1.class).toInstance(childPresenter1); 
      //e.t.c for other variables 

      //Same for child view 
      childView = mock(ChildView.class); 
      binder.bind(ChildView.class).toInstance(childView); 
     } 

     childPresenters = new ArrayList<ChildPresenter>(); 
     childPresenters.add(childPresenter1); 
     //Add all child presenters 

     for(ChildPresenter childPresenter : childPresenters) { 
      when(childPresenter.getView()).thenReturn(childView); 
     } 
    } 
} 

Mockitoは、次のメッセージを表示して文句を言うような問題がラインwhen(childPresenter.getView()).thenReturn(childView);で起こる:

org.mockito.exceptions.misusing。 WrongTypeOfReturnValue:

ChildView $$ $$ EnhancerByMockitoWithCGLIB 2f6a4bd5

はあなたが読んで、エラーの上に取得している理由がわからない場合***

ConcreteChildView1

を返す必要がありますgetViewメソッド()getViewメソッド()で返すことはできません。問題上記の構文の性質上発生する可能性がありますので:

  1. この例外かもしれない誤って書かれたマルチスレッドテストで起こります。並行性テストの制限については、Mockito FAQを参照してください。

  2. スパイは、(spy.foo())。then()構文を使用してスタブされます。メソッドのdoReturn | Throw()ファミリーでスパイをスタブする方が安全です。 Mockito.spy()メソッドのjavadocsの詳細私が理解することができます

が、私がしたいすべてが嘲笑ChildViewは以下を使用して、単一のメソッドを呼び出し確認されたときには、個々の具体的なChildViewを模擬するために、廃棄物と思われる:

verify(childView, atLeast(childPresenters.size())).getView(); 

これを行う別の方法はありますか?私はどうにかして具体的なものの代わりに擬似抽象クラスを使うことができますか?

public ConcreteChildPresenter1<ConreteChildView1> { 

    @Override 
    public ConreteChildView1 getView() { 
     view.buildView(); 
     return view; 
    } 
} 

とすべての子ビューが広がることを抽象ChildViewクラス:ここ

EDITgetView()メソッドの実装方法の具体的なバージョンでの改良に基づいて

public abstract ChildView { 

    public abstract void buildView(); 
} 
+2

それからキャスト付きのAnnswer()はうまくいくかもしれません –

+0

おそらく、実際のビューを挿入して、必要のないメソッドをモックすることができます。 –

+0

あなたはすでに試してみましたか?doReturn(childView).when(childPresenter).getView(); –

答えて

2

それぞれの子のプレゼンターは、すでに理解されるように、することはできません、特定の種類のビューを返しますので、抽象クラスChildViewのモックでそれらを置き換えます。 Get generic type of class at runtime

次にあなたがこの方法でプレゼンターモックを初期化する可能性があります:

for(ChildPresenter childPresenter : childPresenters) { 
    //this getter returns the needed runtime class 
    when(childPresenter.getView()).thenReturn(mock(childPresenter.getViewType())); 
} 

ここで説明するように、あなたが適切な実装を提供する場合にのみ、実行時にChildViewの具体的な種類を取得する方法があります

+0

これはよりよい解決策です。私は 'childView'のインスタンスを作成していないので、正確に検証できないという問題が残っています。しかし、代わりに、返された型が正しいインスタンス型であることを確認することができます。私は一見をして、私の所見を報告します。先端 – Draken

+0

ああためのおかげで、これは我々がそれを行うことができないとして、さらなる問題を提起し、これら 'ChildPresenter'オブジェクトはに注入されているので、私は空のコンストラクタまたは私はに変数を注入することができるものを持っている必要があります。ジェネリックと注射は一般的にうまくいかず、これは厄介な時の一つです。その周りには方法がありますが、それは簡単ではなく、後で混乱を引き起こす可能性があります。私は、個々のビューのモックを作成しなければならないと思う、それは残念だが、私は代替案を見ることができない。 – Draken

+0

これは私の問題を正確に解決するわけではありませんが、これを受け入れたものとしてマークします。私たちはちょっとしたニッチだと感じています。助けてくれてありがとう – Draken

1

を、嘲笑されたChildViewは間違ったスーパークラスに基づいています。私はあなたがGuiceのインジェクタでそれを修正することができると思います。

Guice.createInjector(...//Creates a fake module and does binding for the variables mentioned earlier 
    // ... 
    //Same for child view 
    childView = mock(ConcreteChildPresenter1.class); // this is the fix 
    binder.bind(ChildView.class).toInstance(childView); 
} 
+0

と他の3つの 'ChildView'ベースクラスについてquesitonを更新しますか?これは私ができる具体的なクラスごとにモックを作成しなければならない場合に戻ってきます。しかし、私は抽象メソッドにアクセスする必要があるだけで、テストをより一般的にすることができるので、避けようとしています。 – Draken

+0

'ClassCastException'によれば、正しいモックを作成する必要があります。 'Class getViewClass()'のようなメソッドを 'ChildPresenter'クラスに追加しない限り、モックを手動で一緒に配線する必要があります。悪いニュース、私は知っている。 –

関連する問題