web-dev-qa-db-ja.com

テスト目的で既存のインスタンス変数を上書きする新しいコンストラクターを作成する

次のように、テスト目的でのみ(私のSUTで使用されるDOCを模擬するために)コンストラクターを追加することは良い/悪い習慣ですか?

public class A {
    private B b = new B();
    private C c = new C();

    public A(){
    }

    /***
     * used for test puproses
     * @param a
     * @param b
     */
    A(A a, B b) {
        // overwrite the existing variables
        this.a = a;
        this.b = b;
    }
}

class B {
}

class C {
}

新しいコンストラクターの可視性をパッケージプライベートにして、SUTのAPIを汚染しないようにし、クライアントの使用の便宜のためにSUT内でDOCをインスタンス化することを選択することに注意してください。

[〜#〜] sut [〜#〜]:テスト中のシステム(A)

[〜#〜] doc [〜#〜]:依存コンポーネント(BおよびC)

どう思いますか ?前もって感謝します。

2
isqo

BとCのハードコーディングを避けるために、テストに関係なくこれを行います。実際、bとcを上書きする方法を提供しなかった場合、このコードは拒否します。現在、ハードコードされているのではなく、単に上書き可能なデフォルト値です。それはいい。

6
candied_orange

あなたのコードは私にはよく見えます(2番目のコンストラクターのタイプミスを除いて、以下を参照)。

次の利点がある次のリファクタリングを検討する場合があります。

  1. クラスBとCを不必要にインスタンス化する必要はありません。
  2. フィールドbとcを宣言できますfinal(該当する場合)。

リファクタリング:

public class A {
    private final B b;
    private final C c;

    public A() {
        this(new B(), new C());
    }

    public A(B b, C c) {
        this.b = b;
        this.c = c;
    }
} 
4
Marco

テストを書くのが難しいため、コードのにおいを発見しました。自分でインスタンス化するのではなく、依存関係注入を介してAおよびBオブジェクトを提供することをお勧めします。最終的にはモックを介して簡単にテストできる、より柔軟なアーキテクチャになります。

1
Eternal21

C#では、静的メソッドを使用してそのようなインスタンスを作成することを好みます。また、名前に「ForTesting」が付いているため、目的が明確になります。

それは次のようになります

internal static A CreateWithDependenciesForTesting(B b1, C c1)
{
    A instance = new A
    {
        b = b1,
        c = c1
    };
    return instance;
}

私はJavaプログラマーではないので、その方法がそこで適用できるかどうか(または方法)はわかりません。

0
Bernhard Hiller