单元测试使用Entity Framework Core 1.1.2调用的存储过程

时间:2017-09-07 20:18:58

标签: entity-framework unit-testing testing entity-framework-core

我有一个使用Entity Framework来调用存储过程的方法,存储的proc返回一些数据。

如下所示

public async Task<IActionResult> Get(int customerId)
{
   List<Product> products = _context.Products.FromSql("EXECUTE dbo.SpGatherProductInfo {0}", customerId)
        .ToList();

   if (!products.Any())
   {
      return NotFound();
   }

   return Ok(products);
}

如果这是对表的简单查询,我会创建一个内存数据库,添加一些假的条目,一切都会好的。

但是这使用了存储过程,我该如何对它进行单元测试?

2 个答案:

答案 0 :(得分:0)

您过分关注实施问题。在这种情况下,实体框架是一个实现问题。

这似乎是将这种关注封装到抽象中的好例子。

public interface IProductService  {
    Task<List<Product>> GatherProductInfo(int customerId);
}

并将其注入控制器

public class ProductsController : Controller {
    private readonly IProductService service;

    public ProductsController(IProductService service) {
        this.service = service;
    }

    public async Task<IActionResult> Get(int customerId) {
        List<Product> products = await service.GatherProductInfo(customerId);

        if (!products.Any()) {
            return NotFound();
        }

        return Ok(products);
    }
}

IProductService实现将取决于上下文和实际存储过程执行,而控制器仅依赖于抽象。控制器不应该关注数据的来源。

现在允许控制器在隔离中进行单元测试,而不与实体框架实现问题紧密耦合。

public async Task Product_Not_Found() {

    //Arrange
    var customerId = 1;
    var products = new List<Product>();// Currently empty but could easily
                                       //  be populated for another test.
    var mock = new Mock<IProductService>();
    mock.Setup(_ => _.GatherProductInfo(customerId)).Returns(products);

    var controller = new ProductsController(mock.Object);

    //Act
    var result = await controller.Get(customerId);

    //Assert
    result.Should().NotBeNull()
        .And.BeTypeOf<NotFoundResult>();
}

答案 1 :(得分:0)

我的一位同事想出了如何模拟存储的proc调用。

然后我只是在测试中使用那个模拟。

我在这里写了一篇关于它的详细博客文章,有很多代码所以我不会只是从博客中复制粘贴一切 -

ADO documentation