テストでモックオブジェクトを使用する方法のポイントが欠けていると思います...
あなたがしていることは、同時にテストしながら ProductRepository オブジェクトをモックすることです。それはあまり意味がありません。テストしているオブジェクトをモックしないでください。
テストしたいクラス ProductService があり、それが別のクラス IProductRepository に依存しているとします。ProductService をテストするときは、依存関係である IProductRepository をモックする必要があります。これにより、テスト中のクラスとその (モックされた) 依存関係の間の相互作用を完全に制御できます。
そうすることで、アサーションは、テスト対象のクラスである ProductService が期待することに基づいたものになります。たとえば、 のようなものを使用して ProductService を呼び出す場合productService.GetProductById(1)
、ProductService オブジェクトは正しいパラメーターを使用して IProductRepository メソッドを 1 回だけ呼び出すことが期待されますrepository.GetProductById(1)
。また、IProductRepository が指定したのと同じオブジェクトを ProductService が返すことも期待できます。リポジトリが何をするかに関係なく、それは ProductService の責任です。
そうは言っても、テストは次のようになります。
//Arrange
int testId = 1;
var fakeProduct = new Product{ Id = testId };
var mockRepo = new Mock<IRepository>();
var productService = new ProductService(mockRepo);
mockRepo.Expect(repo => repo.GetProductById(testId)).Returns(fakeProduct);
//Act
Product returnedProduct = productService.GetProductById(testId);
//Assert
mockRepo.Verify(repo => repo.GetProductById(testId), TimesExactly(1));
Assert.AreEqual(returnedProduct.Id, fakeProduct.Id);
私の構文は間違っているかもしれませんが、うまくいけばサンプルはいくつかのポイントを越えます:
- テスト中のシステムをモックしない
- 依存関係をモックする
- 依存関係ではなく、テスト中のシステムの責任に基づいてアサーションを行う