実際のオブジェクトが動的に作成されるときに、テストオブジェクトをどのように注入しますか?


8

依存関係注入を使用してクラスをテスト可能にしたい。しかし、クラスは実行時に複数のオブジェクトを作成し、コンストラクターに異なる値を渡します。簡単な例を次に示します。

public abstract class Validator {
    private ErrorList errors;

    public abstract void validate();

    public void addError(String text) {
        errors.add(
            new ValidationError(text));
    }

    public int getNumErrors() {
        return errors.count()
    }
}

public class AgeValidator extends Validator {
    public void validate() {
        addError("first name invalid");
        addError("last name invalid");
    }
}

(Validatorには他にも多くのサブクラスがあります。)

これを変更する最良の方法は何ですか?ValidationErrorの代わりに偽のオブジェクトを注入できますか?

AbstractValidationErrorFactoryを作成し、代わりにファクトリを注入できます。これでうまくいきますが、この種の依存関係ごとに、たくさんの小さなファクトリーとファクトリーインターフェースを作成してしまうようです。もっと良い方法はありますか?


何をテストしようとしていますか?ValidatorがValidationErrorsを作成することは?ValidationErrorの偽装は役に立ちません。コードの状態では、validateを呼び出すことができるため、Validatorはあまり役に立ちませんが、エラーを生成することはできません。
マイケルブラウン

省略しましたが、ErrorListオブジェクトへのアクセスを提供する他のメソッドがあります。これらを使用してテストできます。
JW01、2011年

関連情報については、stackoverflow.com / questions / 4859523 /…をご覧ください
blueberryfields

回答:


4

クラスユニットをテスト可能にする最も簡単な変更は、

  1. (作成コードを新しい(仮想)メソッドに抽出します-これはすでにあります)
  2. テストされたクラスをサブクラス化し、作成メソッドをオーバーライドして、実際のオブジェクトではなく適切なモックオブジェクトを作成します。
  3. ユニットテストを書いてください:-)

もちろん、これはあまり良くありません。しかし、それはクラスをユニットテストでカバーすることを可能にし、その後、より深い変更でコードを壊すことを恐れることなく、理想的なデザインに向けてリファクタリング始めることができます。

必須の参照:レガシーコードを効果的に使用する

その理想的なデザインについては、例に詳細とコンテキストがないため、多くを伝えることは困難です。テストの目的とテストしたクラスの役割について詳しく教えていただければ、さらに役立つ可能性があります。


これが私の一般的なアプローチですが、この場合、Validatorのサブクラスがいくつかあり、テストには多くの設定が含まれます。テストサブクラスを作成する場合は、Validatorの実際のサブクラスごとにテストサブクラスも作成する必要があります。そのため、セットアップ作業の多くを複製することになります。しかし、おそらくこの場合にはそれが必要です。
JW01、2011年

2

通常、この問題の解決策はプロバイダーパターンです。

public class Validator {
    public Provider<ValidationError> errorProvider;

    public void addError(String text) {
        errors.add(errorProvider.get(text));
    }
}

プロバイダーはファクトリーに似ています。この場合、呼び出されるValidationErrorたびにnewを返しgetます。

詳細については、依存性注入のセクション3.3.2(プロバイダーパターンによる再注入)を参照してください。

たとえば、Guiceはこれを提供しています。より洗練されたものが必要な場合は、AssistedInjectを使用できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.