4

コンストラクターが単体テスト環境では実行できない(実行すべきではない)いくつかのことを実行するシングルトンクラスを使用するいくつかのクラスを単体テストしようとしています。私の理想的なシナリオは、コンストラクターが完全に抑制されてから、テストクラスが呼び出す他のメンバーメソッドをスタブ化することです。私の問題は、コンストラクターを抑制できないように見えることです。

これを解決する方法についての私の理解は、次のようになります。

public class MySingleton extends AbstractSingletonParent {
    public final static MySingleton Only = new MySingleton();
    private MySingleton(){
        super(someVar); // I want the super-class constructor to not be called
        //
        //more code I want to avoid
    }

    public Object stubbedMethod() {}
}

public class ClassToBeTested {
    public void SomeMethod(){
        Object o = MySingleton.Only.stubbedMethod();
    }
}


@RunWith(PowerMockRunner.class)
@PrepareForTest(MySingleton.class)
public class TestClass {
    @Test
    public void SomeTest() {
        suppress(constructor(MySingleton.class));
        mockStatic(MySingleton.class);

        PowerMock.replay(MySingleton.class);
        // invoke ClassToBeTested, etc

        PowerMock.verify(MySingleton.class);

        //make some assertions
    }
}

残念ながら、createMockの呼び出し中に、MySingletonコンストラクターがヒットし、それでもスーパーコンストラクターが呼び出されます。

私は愚かなことをしていますか?これをほぼ正確に実行している例をWebで見つけましたが、非推奨のsuppressConstructorメソッドを使用していました。非推奨にもかかわらず、私もそれを試しましたが、役に立ちませんでした...

私がやろうとしていることは可能ですか?もしそうなら、私は何を間違っていますか?

*編集バージョンが機能するようになりました。

4

3 に答える 3

2

シングルトンのバイトコードを操作できるようにTestClass、注釈を付ける必要があります。@PrepareForTest

また、スーパークラスのctor抑制シグニチャには、somevarのクラスを含める必要があります。現在、デフォルトのコンストラクターを抑制しているだけです。

@PrepareForTestAPIドキュメントを参照してください。こちらも詳細が記載されたブログ投稿です。

FWIW、それは私のために働いています:

@RunWith(PowerMockRunner.class)
@PrepareForTest({EvilBase.class, NicerSingleton.class})
public class TestEvil {

    @Test
    public void testEvil() {
        suppress(constructor(EvilBase.class));
        assertEquals(69, EvilBase.getInstance().theMethod());
    }

    @Test public void testNice() {
        suppress(constructor(EvilBase.class));
        suppress(constructor(NicerSingleton.class));
        assertEquals(42, NicerSingleton.getInstance().theMethod());
    }

}
于 2011-11-11T22:49:46.337 に答える
0

あなたが間違っているのは何なのかわかりません。しかし、設計面では、依存性注入、つまりDIを検討することをお勧めします。

コードをテスト可能にするために、DIを利用してください。DIを使用すると、シングルトンクラスをコンストラクター引数としてテストクラスに渡します。そして今、引数を渡すので、テストケース内でAbstractSingletonクラスのカスタム実装を作成でき、テストケースは正常に機能するはずです。

DIを使用すると、コードのテストが容易になります。

于 2011-11-11T22:53:01.633 に答える
0

シングルトンのインスタンスフィールド(コード内)を、必要なコンストラクターでインスタンス化されたインスタンスで設定するのはどうですか(Reflection APIまたはdp4j'only'を使用してこれらすべてを行うことができます)。

dp4jの出版物のやる気を起こさせる例は、それについて説明しています。

于 2011-11-17T20:54:43.610 に答える