2

ClassAインスタンス化が難しいものに依存するこのJavaをテストする必要があるとしましょうClassB

public class ClassA
{
    public ClassA()
    {
        String configFile = "config_file.xml";

        // I have to pass configFile to instantiate ClassB.
        // And for example if configFile does not exists in the testing machine?
        // Wouldn't it be easier to have an empty constructor for classB to test ClassA?
        ClassB classB = new ClassB(configFile);
    }

    // ...
}

ClassB:

class ClassB
{
    ClassB(String configFile)
    {
        // Set up configs.
    }

    // ...
}

classBテスト目的でのみ内部に空のコンストラクターを作成するのは悪い習慣ですか? それとも、そのために簡略化されたモックを書き直したほうがよいのClassBでしょうか?

4

3 に答える 3

5

SpringGuiceなどを使用して、IoC と Dependency Injection に適したシナリオのようです。

その方法ClassAでは、 のインスタンスが「必要」であることを宣言するだけでClassB、IoC コンテナーが接続され、必要な依存関係が構築されます。

ただし、途中でフレームワークを取得したくない場合は、 からインターフェイス コントラクトを抽出し、それClassBClassA依存して、コンストラクターでそのコントラクトの実装を受け取ることで解決できます。

例えば:

interface SomeContract {
    void someBehavior();
}

ClassBそれを実装してください:

class ClassB implements SomeContract {
{
    ClassB(String configFile)
    {
        // Set up configs.
    }

    void someBehavior() {
        // ...
    }
}

そして、次のように使用します。

public class ClassA
{
    private SomeContract implementation;
    public ClassA(SomeContract implementation)
    {
        this.implementation = implementation;
    }

    // ...
}

そうすれば、単体テストで、モックなど、テストで決定したインスタンスを渡すことができ、コードを変更することなく、それに応じてテストできますClassB

肝心なのは、テスト目的のためだけに追加のコンストラクターなどを作成しないようにする必要があるということです。

于 2012-06-17T13:53:26.790 に答える
5

実際にパラメーターなしのコンストラクターを使用し、 new キーワードで依存関係を作成すると、クラスがテストできなくなります。コンストラクターから ClassB の依存関係を注入することはできないため、それをモックしてテスト対象のコードを分離することはできません。すべての単体テストで両方のクラスをテストする必要があり、それが悪い単体テストになります。代わりに、すべての依存関係をコンストラクター パラメーターとして追加する必要があります。

より良いアプローチは次のとおりです。

public class ClassA
{
    // use an abstraction instead of a concrete class
    private IClassB _classB;

    public ClassA(IClassB classB) 
    {
        _classB = classB;
    }
}

このようにして、IClassB をモックすることができ、ClassB 実装の詳細について心配する必要はありません。

于 2012-06-17T13:54:06.230 に答える
1

私の意見に関しては、通過する構成ファイルが欠落しているか存在しない場合に、デフォルト構成で開始するオプションをクラスBに提供します。

編集済み:Weld / CDI、Hibernateバリデーター、Arquilluanなどのよく知られたアーティファクトも、デフォルトの構成に空の構成ファイルを提供します。記載がない場合は、デフォルト値が適用されます。

于 2012-06-17T13:52:43.337 に答える