10

我对EF很新,我想知道用SQL Server数据库创建EF的最佳方法。之后,我想测试CRUD操作。 EF是以TDD方式实现的,我对这些存储库模式,模拟上下文,假模式等感到困惑。单元测试和实体框架

EF中的CRUD操作,什么东西都会被测试? (DbContext,SaveChanges() ...是否需要测试?)

那么任何想法如何使用基于实体框架的组件进行单元测试? (我正在检查所有这些在Visual Studio 2012中,ASP.NET MVC4)

+2

仅供参考:这些通常被称为集成测试。如果他们是单元测试..你会每隔30秒打一次“运行测试..”(就像你应该在TDD中一样),并且每次测试的数据库往返将使你的测试运行几分钟/小时。集成与其他系统实际集成的测试在预发布时运行。 –

+0

@SimonWhitehead:那么为什么我们使用存储库模式,是否需要,以及混淆和伪装之间的区别是什么 – neel

+0

*之后,我想测试CRUD操作*您想测试与CRUD操作相关的逻辑,或者要测试实体框架? –

回答

5

要测试EF功能,我建议对已知数据编写集成测试。 一种常用方法是作为测试为前提,以你的你的选择基于功能测试的一部分,以建立数据:

例:

  1. 插入已知数据

  2. 运行选择功能与已知数据

  3. 断言导致

以上步骤将测试您的查询和EF绑定/模型。

作用于从EF返回的数据的业务逻辑应该通过嘲讽来抽象EF逻辑。这将使您能够编写单元测试,而不用考虑集成点/数据依赖性,只需测试逻辑即可。

+1

只是为了添加一个可能的点4.将每个测试封装在最后回滚的事务中 - 这样在测试运行后让数据库保持清洁状态 –

2

您也可以使用内存数据库测试您的EF模型。使用Effort作为单元测试数据库的Here is an example

+0

链接已死 –

5

存储库和工作模式单元旨在创建数据访问层和应用程序业务逻辑层之间的抽象层。实现这些模式可以帮助您将应用程序与数据存储区中的更改隔离开来,并且可以促进自动化单元测试或测试驱动开发(TDD)。

只要去Here与exsample的解释。

16

比方说你有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等框架进行集成测试。基本上,您可以将Productscontroller与实际的ProductsRepository实例化,并检查返回的结果。