2011-11-08 14 views
7

ほとんどのSO関連の質問(here,hereおよびthere)を読んでいます。 最後の質問は、静的メソッドをユニットテスト可能と呼び出すコードを作るための4つの選択肢を提案しています。 私は私の特別なケースについて質問したい:私たちは45の静的クラス(状態なし、静的メソッド)を含む「ビジネスロジックレイヤー」または「ルール」プロジェクトを持っています。さらに、それらは自分自身で簡単にテスト可能ではありません。ほとんどの人がデータベースとファイルシステムにアクセスします。とにかくデータベースにアクセスするために、いくつかのMapperクラス(すべてのマッパーはシングルトン)の一意のインスタンスを使用します。 ユニットテストをしようとするたびに、私はこの壁にぶつかります。最大の問題は、これが非常に重要なコードであり、変更が非常に慎重に計画されることです。 私の質問:このユニットをテスト可能にするにはどうすればよいですか?私は45のインタフェースを書いて、依存性注入を使うべきですか?それでも、どのようにマッパーをスタブ/モックするのですか?静的メソッドを呼び出すユニットテストコード

PS:私は、 『レガシーコードの操作』マイケル羽を読んでいるので、直接の言及は、(歓迎されている他の本すぎ:)

編集:一部の人が言ったので、解決策は、プラットフォーム依存であるかもしれません

答えて

10

予期しない方法で中断する可能性があるため、コード内の何かを変更しようとする人はいないでしょう。誰もがあなたが状況を改善していることを理解していることを確認してください:あなたの変更を前とは違ったコードが、を壊すかもしれない、これらの破損は、彼らが発見されているたらを発見しただろう、彼らは永遠にを固定します。

つまり、次のステップは、あなたの経験とチームの得意先によって異なります。これはあなたのテストからINSTANCEを上書きすることができ、非常に簡単な変更をある

Mapper { 
    public static Mapper INSTANCE = new Mapper(); // NEW code 

    protected void doImpl() { // NEW CODE 
     ... code copied from impl()... // OLD code, NEW PLACE 
    } 

    public static void impl() { // OLD code 
     INSTANCE.doImpl(); // NEW code 
    } 

    // OLD code ... 
} 

:あなたが安全な再生したい場合は、この(Java構文)のようなコードを使用します。プロダクションコードの場合、何もしないので、デフォルトではコードは以前と同じように動作します。

このようにして、一度に1つのメソッドを置き換えることができます。このパスはいつでも停止することができます。各変更には数分しかかかりません。リファクタリングが必要です。コードはこれまでと同じように動作します。各変更は非常に小さく、何かを壊すことができないので、1つのメソッドを置き換え、前に書き込めなかった単体テストをすべて書き、すすぎ、繰り返すことができます。最後に、すべての静的メソッドを再作成する必要がない/必要がない場合は、この方法では必要なすべての余裕が得られます。

第2のステップでは、DIやその他の技術を導入して、あなたを幸せにすることができます。このアプローチの利点:複雑な変更になると、あなたを保護する単体テストが既に用意されています。

DIを使い始めるのであれば、あなたを守るための適切な単体テストがなくても、あらゆる種類の場所で多くのコードを変更する必要があります。

2

あなたの質問は本当にプラットフォームに関連しています。Microsoftの世界では、静的メソッドをテストするためにMicrosoft Molesを使用できます。静的メソッドをモックします。

Javaの世界にはおそらく他のツールがあるか、静的な使用を避けるべきです。一般的には他のプラットフォームで

他のツールがあるなど

、任意の静的メソッドは、あなたのコードが少ないテスト可能になります。私の選択肢では、スタティックとシングルトン(グローバルな状態)を避けることができます。後で何かを変更する必要がある場合、テスト可能なコードはコードの中で最も重要な部分です。テスト可能なコードは通常、より読みやすくなります。

Moles and Pex

3

マッパークラスのインタフェースを作成し、新しいMOC実装とマッパー機能を交換してください。マッパーのインスタンスを生成する抽象ファクトリを実装する必要があると思います。したがって、IMapperFactoryを作成し、このDBMapperFactoryとMocMapperFactoryの2つの実装では、このオブジェクトのインスタンスをマッパーにアクセスし、このインスタンスを使用してこれらを生成するコードに渡します。

G1。

+1

それは静的メソッドをテスト可能にすることを世話しますが、それを呼び出すコードはどうですか?別の言葉では、ちょうど好奇心が強い...「GI」は何らかの種類の署名、または略語ですか? (私はアルゼンチン出身です) –

+0

G1 == Good Luck :) Mapperを使用するコードでは、シングルトンによってgetInstanceの代わりにファクトリインターフェイスを使用するように適合させる必要があります。 – AlexTheo

1

あなたが使っている言語や環境がわからなくても、静的なクラスを嘲笑することができます。

私はあなたが言ったようにまったく同じコードベースを持っていました。数十の静的クラス(パニックコード生成はしません)のインターフェイスとデフォルトの実装を作成しました。デフォルトでは、シングルトンに委任されただけです。

呼び出しクラスは、デフォルトimplsを使用してDIに切り替えられましたが、テストするのがはるかに簡単でした。他の静的クラスまたはシングルトンに依存する静的クラスは、デフォルトのimplsを使用して移動されます。

シングルトンを他のクラスと同じようにモックします。getInstance(または同等のもの)があれば、必要なものを返すことができます。または、同じルートを使用してDIを使用することもできます。

+0

さて、私は.NET(更新された質問)を使用しています。静的クラスを簡単に模擬することは可能ですか? –

+0

@dario_ramos私は分かりませんが、ピアの答えはあなたができることを意味します。 –

1

優秀な質問! Mapperクラスは、シングルトンMapperクラスから継承した新しいクラスを作成し、それを使用してデータベースへのすべての呼び出しをインターセプトできます。

関連する問題