2層ソリューションがあるとしましょう
MyApp.Web
MyApp.Data
データレイヤーには、次のようなものがあります。
public class ProductsRepository : IProductsRepository
{
public List<Product> GetAll()
{
//EF stuff
return _dbcontext.Products;
}
}
IProductsRepository の場所
public interface IProductsRepository
{
List<Product> GetAll();
}
MyApp.Web では、これを行う傾向があります。
public class ProductsController : Controller
{
private readonly IProductsRepository _productsRepository;
public ProductsController(IProductsRepository productsRepository)
{
_productsRepository = productsRepository;
}
public ActionResult Index(int page=1)
{
var allProducts = _productsRepository.GetAll();
return View(allProducts)
}
}
実行時にProductsRepositoryをコンストラクターに入れるのは誰ですか? これには、 Ninjectフレームワークのような依存性注入が使用されます。しかし、なぜ?これにより、 ProductsRepositoryを偽造し、このようにすることができるためです。
public class FakeProductsRepository : IProductsRepository
{
public List<Product> GetAll()
{
return new List<Product>
{
new Product { Name = "PASTE" }
new Product { Name = "BRUSH" }
},
}
}
そして、このようにコントローラーをユニットテストします
[TestMethod]
public void IndexGetsAllProducts()
{
//Arrange
var fakeProductRepo = new FakeProductsRepository();
var productsController = new ProductsController(fakeProductRepo);
//Act
var result = productsController.Index(1) as ViewResult;
//Assert
var model = result.Model as List<Product>;
Assert.AreEqual(2, model.Count);
}
基本的に、単体テストが高速でデータベースに依存しないように、データベースを偽造しています。偽装のためにMoqのようなモッキングフレームワークを使用することがありますが、これは基本的に同じことを行います。
ProductsRepositoryをテストする場合は、外部ソースに依存するため、単体テストとは呼ばれなくなりました。それらをテストするには、本質的にEntityframeworkをテストしています。
単体テストと組み合わせて、人々は Specflow のようなフレームワークを使用して統合テストを行います。基本的に、実際のProductsRepositoryを使用してProductscontrollerをインスタンス化し、返される結果を確認できます。