2016-09-30 24 views
0

における一般的なインタフェースのモックアップすることができません:TextModelImageModelScoringModel:このインタフェースは、3つの具象クラスによってサブクラス化され私は一般的なインタフェースモックとしたいJMockit

public interface IModel<T, S> { 
    public S classify(T entity); 
} 

を。これらの具象クラスのそれぞれは、異なるTおよびSパラメータを有する。

私は、引数として、具体的なモデルクラスを受信して​​、モデルの嘲笑バージョンを生成し、一般的な方法を書いた:私はIModel::classifyは、その入力と出力の両方のための一般的な種類を持っていることを知っている

private <T extends IModel<?, ?>> T mockModel(Class<T> modelClass) { 
    return new MockUp<T>() { 
     @Mock public Object classify(Object entity) { return null; } 
    }.getMockInstance(); 
} 

が、私モックアップ内で実際のジェネリックメソッドを使用する方法が見つかりませんでした。

java.lang.IllegalArgumentExceptionが::。comの戻り値の型com.classificationmanager.model.TextModelと互換性のない型com.classificationmanager.modelの価値$のImpl_IModel

このメソッドを呼び出す

は私が IllegalArgumentExceptionを取得します。 (ModelFetcherTest.java:110) at com.classificationmanager.model.ModelFetcherTest.mockAllFactories(ModelFetcherTest.java:ModelFetcherTest.java:ClassMemoryFetcherTest.maxAllFactories) 109).......(残りを惜しまない)

私の代わりにTとSのObjectを取得して返すことは問題だと思ったが、モックメソッドを削除し、ちょうどクラスをからかったとき、私は同じ例外を取得:

private <T extends IModel<?, ?>> T mockModel(Class<T> modelClass) { 
    return new MockUp<T>() { 
    }.getMockInstance(); 
} 

私はスイッチを行うことができます - ケースと具体的なクラスを返すが、それはちょうど厄介かもしれません。

Expectations APIを使用しているすべての回避策も私にとっては役に立ちます。 ( - XYの問題の可能性場合、私はまだ質問を理解していないが)

10倍

+0

なぜ@Mocked TextModelを使用しないのですか? –

+0

私はできましたが、ImageModel、ScoringModel、今後IModelのすべての具体的なサブクラスを模倣する必要があります – KidCrippler

+0

質問で暗示されているように、 'mockModel(TextModel.class)'を呼び出すことでこれをやっていませんか? –

答えて

1

はたぶん次の例では助けることができます。

public final class ExampleTest { 
    public interface IModel<T, S> { S classify(T entity); } 

    static class TextModel implements IModel<Integer, String> { 
     @Override public String classify(Integer entity) { return "test"; } 
    } 

    static class ImageModel implements IModel<String, Image> { 
     @Override public Image classify(String entity) { return null; } 
    } 

    @Test 
    public void createNonMockedInstanceForAnyModelClass() { 
     IModel<Integer, String> m1 = mockModel(TextModel.class); 
     String s = m1.classify(123); 

     IModel<String, Image> m2 = mockModel(ImageModel.class); 
     Image img = m2.classify("test"); 

     assertEquals("test", s); 
     assertNull(img); 
    } 

    <T extends IModel<?, ?>> T mockModel(Class<T> modelClass) { 
     // Or use newUninitializedInstance in case the model class doesn't 
     // have a no-args constructor. 
     return Deencapsulation.newInstance(modelClass); 
    } 

    @Test 
    public void mockAllModelImplementationClassesAndInstances(
     @Capturing IModel<?, ?> anyModel 
    ) { 
     IModel<Integer, String> m = new TextModel(); 
     String s = m.classify(123); 

     assertNull(s); 
    } 
} 
+0

答えが10倍であれば、 'Deencapsulation :: newInstance'メソッドは私の問題の素晴らしい回避策です。 2回目のテストでは、「キャプチャ」によって注釈が付けられたフィールドは正確に何をしますか?テスト中に 'anyModel'入力パラメータの使用法はありません。 – KidCrippler

+0

'@ Capturing'は、模擬フィールド/パラメータ(およびそのインスタンス)の宣言された型を実装/拡張するすべてのクラスに対して、' @ Mocked 'の効果を拡張します。 –

+0

はい、私は知っていますが、あなたが提供したテストでは 'TextModel'インスタンスが全く模倣されていないように見えるだけで、具体的な実装を呼び出し、実際にnullを返すことを確認します。私は何が欠けていますか? – KidCrippler

関連する問題