0

シンプルなアプリを構築するために.net mvc3を使用しています。私はいくつかのテストケースを書きましたが、そのうちの 1 つに問題があります。Moq を使用してドメイン サービスをモックしています。次の 2 つの方法があります。

List<Customer> customersRepo =
{
  new Customer{
   Id = 0,
   Name = "Jojo"
  },
  new Customer{
   Id = 1,
   Name = "John"
  }
}

mock.Setup(m => m.GetByName(IsAny<string>())).Returns<string>(
 n =>
 customersRepo.Where(c => c.Name == n)
);

mock.Setup(m => m.GetById(IsAny<int>())).Returns<int>(
  n=>
  customersRepo.Where(c => c.Id == n)
);

問題は、モック オブジェクトのメソッドを使用して顧客を名前でフェッチすると、要求したものを取得できるのに、ID でフェッチしようとすると、常にモック オブジェクトから null オブジェクトを取得することです。ID 0 と両方で試しました1. 何が問題なのですか?

ありがとう

4

2 に答える 2

1

最初またはデフォルトの顧客に戻る必要があると思います:

mock.Setup(m => m.GetById(IsAny<int>())).Returns<int>(
  id =>
  customersRepo.FirstOrDefault(c => c.Id == id)
);

また、モックでリポジトリ ロジックを再実装する必要がないことも覚えておいてください (これは奇妙で非常に脆弱です)。モックです。ロジックなしで、必要な結果をモックできます。

mock.Setup(m => m.GetById(42)).Returns<int>(new Customer { Id = 42 });

モックを使用してインタラクションを検証します。つまり、リポジトリのクライアントが、予期されるパラメーターで予期されるメソッドを呼び出したことを確認します。


あるサービスのビジネス ロジックをテストする場合、サービスはテスト対象のシステム (SUT) であり、モックを作成しないでください。ただし、サービスにビジネス ロジックとデータ アクセス ロジックの両方が含まれていると、処理が多すぎます。インターフェイスを実装するリポジトリ クラスにデータ アクセス ロジックを抽出します。

public interface ICustomerRepository
{
    Customer GetById(int id);
    // other methods related to customr data access
}

次に、サービスをこのインターフェイスに依存させます (依存関係の逆転)。

public class YourService
{
   private readonly ICustomerRepository _repository;
   // dependency injection
   public YourService(ICustomerRepository repository)
   {
       _repository = repository;
   }

   public void ExecuteSomeBusinessLogic()
   {
       // your code will go here
   }
}

次に、サービスのテストを作成します。したがって、サービスには依存関係 (顧客リポジトリ) が必要です。この依存関係をモックする必要があります。そして、サービスが期待どおりに依存関係と対話することを確認します。たとえば、ExecuteSomeBusinessLogic テストでは、サービスが ID が 42 の顧客を要求することを確認する必要があります (はい、奇妙なビジネス ロジックです)。

[Test]
public void ShouldPerformGoodStuffWhenCustomerFound()
{
    // Arrange
    var mockRepository = new Mock<ICustomerRepository>();
    mockRepository.Setup(r => r.GetById(42)).Returns(new Customer { Id = 42 });
    var service = new YourService(mockRepository.Object);
    // Act
    service.ExecuteSomeBusinessLogic();
    // Assert
    mockRepository.VerifyAll();
    // check other stuff
}

カスタムがデータベースに見つからなかった場合のテストを作成する場合は、異なるリターンを設定するだけです:

mockRepository.Setup(r => r.GetById(42)).Returns(null);
于 2013-07-09T11:57:56.550 に答える
0

私は実際にインフラストラクチャを少し変更しました..今、私のサービスはコンストラクターで DataSource インターフェイスオブジェクトを取得します..これは独立したデータソースであり、顧客オブジェクトを取得するためにそれに依存しています. ビジネスルールをチェックし、ユーザー入力の必要なサニテーションを行った後..だから今、私はユニットテストで私のデータソース(顧客オブジェクトのリスト)をモックし、このモックされたレポで私のサービスのインスタンスをフィードします顧客オブジェクトの..この方法で、既にコード化されたサービス ビジネス ロジックの正確性をテストできます。以前は、サービスを特定のデータ ストレージ (つまり、EF DbContext を使用する db) と結合していましたが、既に db と結合されているため、単体テストでサービスを使用するのは少し困難でしたが、変更したくありませんでした。単体テストを実行するためだけにデータベースの状態に戻します。

于 2013-07-09T12:38:50.177 に答える