1

テストしたい次の関数があるとします。

public void CancelOrder(Order order)
{
    order.Status = "Cancelled";

    _emailService.SendEmail(order.User.Email, "Your order has been cancelled!");
}

現在、Order クラスは SubSonic で生成されたクラスであり、その User プロパティは遅延ロードされています。つまり、order.User.Email を呼び出すと、実際に SQL ステートメントを実行して User をフェッチします。

これを単体テストしたい場合、単体テストがデータベースにヒットすることを本当に望んでいないため、問題が発生します。

私の現在の解決策は、 CancelOrder 関数を次のようにリファクタリングすることです。

public void CancelOrder(Order order)
{
    order.Status = "Cancelled";

    User user = _userRepository.GetByUserID(order.UserID);

    _emailService.SendEmail(user.Email, "Your order has been cancelled!");
}

次に、_userRepository.GetUserByID() 呼び出しをスタブ化して、ハードコーディングされた User オブジェクトを返すことができます。

これはこれを行うための最良の方法ですか?すべてのデータ アクセスは、プロパティ内に隠されるのではなく、リポジトリを介して行われるため、2 番目の実装の方がクリーンであると主張できると思います。

4

2 に答える 2

0

ユニットテストをデータベースにヒットさせたくないのはなぜですか?MBUnitを使用してテストケースを作成している場合は、単体テストにRollBack属性のマークを付けるだけで、データベースへの変更がロールバックされます。

私は常に、ビジネスレイヤーを対象とする単体テストケースを作成することを好みましたが、実際にはデータベースにpingを実行して、単体テストがアプリケーション自体が使用するものに最も類似するようにします。

于 2009-04-01T14:14:35.473 に答える
0

必要な最低限の機能を提供する独自の Order-alike インターフェイスを定義し、それを CancelOrder メソッドの引数の型として使用します。

interface Order {
  public void Status(...); // or property
  public string UserEmail():
} 

次に、データベースを呼び出す SubsonicOrder などのインターフェースの委任実装を作成します。テストでスタブ実装を使用します。Order インターフェースには、よりリッチなモデルが必要になるかもしれません。これはほんの一例です。

必要に応じて、電子メール サービスについても同じことを行います (おそらく、コンストラクターまたはサービス ロケーターを介した依存性注入によって)。

于 2009-03-28T09:05:06.717 に答える