2011-07-28 7 views
5

私はこのように実装I1から​​のアダプタがあります。複雑すぎるコードのないJUnitをアダプタに書き込む方法は?

class BAdapter() implements I1 
{ 
    void logA() { // nothing } 
    void logB() { new BLogger().log() } 
    void logC() { // nothing } 
} 

私はそれが機能を確認し、JUnitテストを書きたいと思いますが、私が代わりに私のモックオブジェクトを注入することはできませんので、私は、それは少し問題が見つかりましたBLogger、または戻り値を確認してください。私はいくつかの解決策を見つけましたが、わかりませんが、これは最高です。

ケースワン:BAdapterクラスにvoid setLogger(Logger l)を追加します。

class BAdapter() implements I1 
{ 
    private Logger logger = new BLogger(); 

    public void logB() { logger.log() } 
    public void setLogger(Logger l) { logger = l } 
    .. //rest of methods 
} 

短所:「実際の」テストコードでは使用されないセッターを追加する理由を教えてください。

ケース2: 保護されたファクトリメソッドとサブパッケージBAdapterをテストパッケージに追加します。

class BAdapter() implements I1 
{ 
    public void logB() { createLogger().log() } 
    protected Logger createLogger() { retrun new BLogger() } 
    .. //rest of methods 
} 

class BAdapterForTesting extends BAdapter() 
{ 
    protected Logger createLogger() { retrun new MockBLogger() } 
} 

短所:これはきれいで洗練された解決策であるとは限りませんが、私はここで大きな問題は見当たりません。

ケース3: 抽象的な工場パターンを使用します。

テストで
class BAdapter() implements I1 
{ 
    public void logB() { AbstractFactory.getFactory().getBLogger().log() } 
    .. //rest of methods 
} 

そしてどこか:

AbstractFactory.setFactory(new MockLoggersFactory()) 

短所:これはあまりにも複雑で、そうではありませんか?

ケース4: たとえば、ログが実行されたときにブール値を返します。例えば。

class BAdapter() implements I1 
{ 
    Boolean logA() { return false; } 
    Boolean logB() { return new BLogger().log() } 
    Boolean logC() { return false; } 
} 

短所:これはまあまあです。誰も本当の非テストコードでそれを必要としないときに、何らかの価値を返すのはなぜですか?

改善されたソリューション? もっと良いことはありますか?

答えて

2

あなたのコードからは、テスト対象のクラスが達成しようとしているものを正確に伝えるのは難しいですが、 私は '実際の'コードにも注入を使用するという警告とともにケース1に行きます。

注射の利点の1つは、クラス(この場合はアダプタ)をより再利用できるようにすることです。 logBメソッドを常にBLoggerのインスタンスに委任するように強制すると、その動作はコンパイル時に石に設定されます。アダプタを別のタイプのLoggerに委譲したい場合、私はそれを使用できません。したがって、アダプタは少ししか再利用できません。

+0

JUnit in Actionの本でも同様のアプローチが見つかりました。テストコードは他のコードと同じようにコードのクライアントであるため、Unitテストの要件に合うようにコードを再コンパイルまたは更新するとよいでしょう。 –

0

特にテストで使用されるIMVHOコードを作成すると、使用される予定のない機能が公開される可能性があるため、他の場所では使用できませんが、涼しくてひどく驚くこともあります。

これは、一般的には非常に良いアプローチですが、まだテスト中に使用されている場合は残念です。

私は便利な方法でクラスでprivateフィールドを変更することができますPowerMockのようないくつかの追加的なモックフレームワーク使用してお勧め:

class BAdapter() implements I1 
{ 
    private Logger logger = new BLogger(); 

    public void logB() { logger.log() } 
    .. //rest of methods 
} 

をして、いくつかのモックにスワップにフィールドをテスト中:

Whitebox.setInternalState(loggerInstance, "logger", new MockLogger()); 

詳細情報: http://code.google.com/p/powermock/wiki/BypassEncapsulation

モッキングフレームワークはテスト中に大きな資産であり、そのために役立っていますたくさんあるよ。