2

独自のアプリケーション用のプラグインを開発しています。

仕様は本質的に、指定された名前の関数があるということです。インストールすると、親アプリケーションがプラグインの関数を呼び出し、さまざまなパラメーターを渡します。

プラグインを単体テストしたいのですが、親アプリケーションのソースにアクセスできません。関数をテストするために必要なパラメーターをインスタンス化できません。

この特定のケースでは、パラメーターは、アクセスする 2 つのデータ要素と、アクセスするログ機能を持つオブジェクトです。サンプルのモックアップはそれほど難しくありませんが、ちょっとしたジレンマに直面しています...

public PerSpecResponseObject myPluginFunction(ThirdPartyObject iUseThis){
...
}

自分のオブジェクトを「myPluginFunction」に渡すことができません。ThirdPartyObject 型が必要です。インターフェイスを定義する場合、ThirdPartyObject にアクセスしてインターフェイスを実装することを指定することはできません。プラグインがインターフェイスを実装しているため、 ThirdPartyObject をサブクラス化してジェネリック パラメーター ( <? extends ThirdPartyObject>) を使用できず、パラメーターの型が制限されます。私はモッキングを調べましたが、興味深いものでしたが、私の状況には当てはまらないようでした。

この状況にはどのような解決策がありますか?

4

2 に答える 2

2

親アプリケーションのソースにアクセスできる場合は、単体テストではなく統合テストになります。

モックできThirdPartyObjectます。実際、やりたいことが単体テストである場合は、モックする必要があります。ThirdPartyObject

と同じ FQN を持つクラスを作成するだけで、ThirdPartyObject配布されないようにテスト フォルダーに保持します。

これは私が考えることができる最も簡単です。

于 2013-08-25T12:45:52.553 に答える
2

実数を構築できることが確かに最善ThirdPartyObjectです。

このクラスを参照する必要があるため、このクラスを含むサード パーティ ライブラリがクラス パスに少なくともいくつかあります。ライブラリにもあるファクトリを使用するなど、それを構築する方法はありませんか? または、別のオブジェクトを構築し、プラグインをインスタンスで呼び出すメソッドを呼び出すことThirdPartyObjectによって?

これは統合テストと呼ばれることもありますが (メインアプリケーションとの統合をテストしているため)、テストがデータベースにデータを入れたり、他のことをしたりしない限り、古典的な意味での単体テストと見なすこともできます。他のテストに影響を与える可能性があります。

上記が不可能な場合は、MockitoThirdPartyObjectなどを使用してモックアウトすることもできます。テスト コードが必要以上に実装に結合されていないことを確認してください。一部の人々は、クラスのすべての依存関係をモックアウトし、それらの依存関係に対するすべてのメソッド呼び出しを検証する必要があると考えています。彼らは多くの強力な結合と冗長性を導入しています。

あなたが言及した2つの問題に関して、両方を回避する方法があります:

ThirdPartyObject1)インターフェースを実装することはできないと言います。それは本当ですが、このインターフェイスを実装し、ThirdPartyObject. 次に、メイン アプリケーションによって呼び出されるメソッドは、このインターフェイスを使用する実際のプラグイン メソッドの実装に単純に委譲します。

例(ThirdPartyObject単一のメソッドがあるとしますvoid thirdPartyMethodCall()

public interface InterfaceForThirdPartyObject {
    void thirdPartyMethodCall();
}

public class ThirdPartyObjectAdapter implements InterfaceForThirdPartyObject {
    private final ThirdPartyObject delegate;

    public ThirdPartyObjectAdapter(ThirdPartyObject delegate) {
        this.delegate = delegate;
    }

    public void thirdPartyMethodCall() {
        delegate.thirdPartyMethodCall();
    }
}

// your actual plugin implementation, not directly exposed to the main app
public class MyPlugin {
    public PerSpecResponseObject myPluginFunction(InterfaceForThirdPartyObject iUseThis){
        // this will contain your actual logic that you want to test
    }
}

// this is the plugin as exposed to the main app
public class MyPluginAdapter implements PluginInterface {
    private final MyPlugin delegate = new MyPlugin();

    // this is called by the main application
    public PerSpecResponseObject myPluginFunction(ThirdPartyObject iUseThis) {
        delegate.myPluginFunction(new ThirdPartyObjectAdapter(iUseThis));
    }
}

2) プラグインが の代わりに as メソッド引数ThirdPartyObjectを持つインターフェイスを実装しているため、サブクラス化できないと言います。なぜそれが問題になるのかわかりません: as パラメーターを取るメソッドは、 のサブクラスのインスタンスを問題なく受け取ります。ThirdPartyObject? extends ThirdPartyObjectThirdPartyObjectThirdPartyObject

于 2013-08-25T14:20:14.507 に答える