6

Configurationシステム全体のデータ設定を担当する静的クラスがあります。コンストラクターでレジストリから特定の値を読み込み、すべてのメソッドはこれらの値に基づいています。レジストリから値を取得できない場合 (アプリケーションがまだアクティブ化されていない場合に発生する可能性があります)、例外がスローされ、これは に変換されますがTypeInitializationException、これは問題ありません。

NUnit を使用して単体テストを作成し、Configuration のコンストラクターがすべてのケース (通常の値、空白の値、Null 値) を正しく処理することを確認しました。各テストは、関連する値を使用してレジストリを初期化し、構成内のメソッドを呼び出します。問題は、NUnit が最初に Null テストを実行することを決定したことです。レジストリをクリアし、構成を初期化し、例外をスローします。すべて問題ありません。しかし、これはコンストラクターが失敗した静的クラスであるため、他のテストのためにクラスを再構築することはなく、すべて失敗します。

Null テストがなくても問題が発生する可能性があります。なぜなら、Configuration はおそらく (推測しているように) それを使用するすべてのクラスに対して 1 回初期化されるからです。

私の質問は次のとおりです。リフレクションを使用して各テストのクラスを再構築する必要がありますか、またはこのクラスを再設計して、コンストラクターではなくプロパティのレジストリをチェックする必要がありますか?

4

4 に答える 4

10

Configuration私のアドバイスは、クラスを少し再設計することです。あなたの質問は本質的に理論的なものであり、少し実用的な側面 (単体テストの失敗) があるため、私のアイデアをバックアップするためのリンクをいくつか提供します。

まず、Configuration非静的クラスを作成します。google のエンジニアである Miško Hevery は、 OO Design for Testabilityについて非常に優れたスピーチを行っており、特にテストしたい場合に、悪い設計の選択としてグローバルな状態に特に触れています。

構成はRegistryProvider、コンストラクターを介してインスタンスを受け入れることができます (依存性注入の原則について聞いたことがあると思います)。RegistryProvider責任はレジストリから値を読み取るだけであり、それが唯一のことです。をテストするときに、特定のレジストリ エントリの値をハードコードする場所Configurationを提供しますRegistryProvider stub(スタブとモックが何であるかがわからない場合は、Google で検索してください。本質的に単純です)。

さて、利点:

  • unit testsレジストリに依存していないので、あなたは良いです
  • あなたはグローバルな状態を持っていません(テスト容易性)
  • あなたのテストは互いに依存していません(それぞれが別々のConfigurationインスタンスを持っています)
  • テストは実行される環境に依存しません (レジストリにアクセスする権限がない場合でも、Configurationクラスをテストすることはできます)

依存性注入が苦手だと思われる場合は、Mark Seemann の天才によって人間の魂に提供された .NET 依存性注入と呼ばれる素晴らしい芸術とエンジニアリングの作品をお勧めします。.NET 開発者向けの、クラス設計について読んだ中で最高の本の 1 つです。

私の答えをより具体的にするには:

テストごとにリフレクションを使用してクラスを再構築する必要がありますか?

いいえ、テストでリフレクションを使用しないでください (それ以外の場合に限ります)。リフレクションはあなたをテストします:

  • 壊れやすい
  • わかりにくい
  • 維持するのが難しい

オブジェクト指向のプラクティスをカプセル化と組み合わせて使用​​し、実装を隠蔽します。次に、外部の動作のみをテストし、内部の実装の詳細に依存しないでください。これにより、テストは外部の動作のみに依存し、内部の実装には依存しなくなります。内部の実装は大きく変わる可能性があります。

コンストラクターではなくプロパティでレジストリをチェックするように、このクラスを再設計する必要がありますか?

私の回答で説明されているようにクラスを設計すると、クラスがレジストリにまったくアクセスしていないことをテストできます。これは単体テストの基礎です。外部システム (データベース、ファイル システム、Web、レジストリなど) に依存しないでください。レジストリにアクセスできるかどうかをテストしたい場合は、レジストリへの書き込みとレジストリからの読み取りを行う個別の統合テストを作成します。

RegistryProvider現在、コンストラクターでレジストリを読み取る必要があるか、オンデマンドでレジストリを遅延して読み取る必要があるかを判断するのに十分な情報がありません。これConfigurationは難しい質問です。しかし、私は間違いなく言うことができます-できる限りグローバル状態を避け、テストの実装の詳細への依存を最小限に抑え(これはオブジェクト指向の原則全体に関連しています)、オブジェクトを分離して、つまり外部にアクセスせずにテストするようにしてくださいシステム。次に、例外的なケースを模倣できます。たとえば、レジ​​ストリが利用できない場合、クラスは期待どおりに動作しますか? Configurationクラスの静的メンバーを介してレジストリに直接アクセスする場合、このようなシナリオを再現するのは非常に困難です。

于 2013-03-31T14:48:00.030 に答える
1

静的クラス/メソッドは、単体テストが難しいことで有名です。(また、現在行っていることは単体テストではなく、統合
テストで あることにも注意してください(テストのレジストリ値を変更しています)。)

クラスをテスト可能にするか、静的にするかを選択する必要があると思います。

あなたが作ることができる妥協は、メインの静的クラスによって呼び出される別の非静的クラスに「論理」ビット (つまり、検証など) を移動することです。
その非静的クラスは簡単にテストできます。

于 2013-03-31T14:48:39.687 に答える
0

私ならリデザインを選びます。また、何か問題が発生した場合に TypeInitializationException が発生すると、ユーザー/開発者が混乱する可能性があります。

于 2013-03-31T14:39:48.390 に答える