0

1 か月前に「Art of Unit Testing」という本を読み終え、今日ようやく Rhino Mocks を使用して、デバイス (UDP) にメッセージを送受信し、データベースからデータを保存/ロードするサービスの単体テストを開始する時間がありました。
もちろん、データベースと UDP 通信を分離したいと考えています。

たとえば、データベースアクセスの場合、静的メソッドを持つクラスがいくつかあります。それらを呼び出しましょう。

  • エリアADBアクセス
  • エリアBDBアクセス
  • エリアCDBアクセス

これらのクラスには、データベース アクセスを実行する静的メソッドがありました。
それらをスタブできるようにするために、メソッドを public virtual にしました。

次に、コード上のこれらのクラスのインスタンスを置き換えることができるように、コードのリファクタリングを開始しました。
さまざまなことを試した後、物事をとても簡単にするように見えるファクトリークラスにたどり着きました。

public class ObjectFactory
{
    private static Dictionary<Type, object> Instances = new Dictionary<Type, object>();

    public static T GetInstance<T>() where T : new()
    {
        if(Instances.ContainsKey(typeof(T)))
            return (T)Instances[typeof(T)];

        return new T();
    }

    public static void SetInstance<T>(object obj)
    {
        Instances[typeof(T)] = obj;
    }
}

次に、コードで使用できます

private AreaADBAccess DBAccess = ObjectFactory.GetInstance<AreaADBAccess>();

そして、テストメソッドで私は次のようなことをします

AreaADBAccess dbAccess = mocks.Stub<AreaADBAccess>();
using (mocks.Record())
{
...
}
ObjectFactory.SetInstance<AreaADBAccess>(dbAccess);
//Invoke the test method
...

これは最初の解決策であり、より良い方法で実行できることを認識しています。
コメントして、ベストプラクティスを教えていただけますか?
また、メソッドを仮想として定義するのではなく、インターフェイスが必要な理由を説明してもらえますか? メソッドヘッダーを 2 か所繰り返すのは無駄に思えます。
ありがとう!

4

1 に答える 1

4

おそらく、Windsor、StructureMap、Ninject などの IoC コンテナーを使用すると、作業がはるかに簡単になります。実際、それらは手動で作成した「ファクトリー」としても機能しますが、はるかに強力です。

また、クラスのモック依存関係を自動的に作成する自動モック コンテナーもあるため、追加のコード行を節約し、テストの脆弱性を軽減できます。

クラスではなくインターフェイスの必要性に関する質問については、基本的に依存関係の逆転の原則であり、上位レベルのモジュール (クラス) は下位レベルのモジュール (クラス) に依存してはならず、両方とも抽象化に依存する必要があると述べています。インターフェイスはそれらの抽象化です。あなたの人生をより楽にしてくれる SOLID の原則をご覧になることをお勧めします。少なくとも私にはそうでした..

于 2010-02-24T18:53:44.230 に答える