在实现存储库(DAL)和Mocking DAL for TDD时处置对象上下文

时间:2016-05-20 13:33:28

标签: entity-framework unit-testing tdd

我遇到了一个问题,我无法弄清楚如何正确处理我每次实例化一个新对象时创建的对象上下文。

public bool HasNewOrders(){

    using(var entityObject = new entityObject(dbconnectionString)){
       var newOrders = entityObject.GetNewOrders();
   }
   //some logic
}

所以问题是,我的服务每30秒创建一个OrderBLL的新实例,然后运行一个方法来查看数据库中是否有新订单。

所以每30秒我创建一个没有被处理掉的新的entityObject。代码的旧实现是使用using语句编写的。

 // Swift
 Digits.sharedInstance().startWithConsumerKey("your_key", consumerSecret: "your_secret")

使用这个using语句的问题是我无法模拟出entityObject,并且可以轻松地在OrderBLL类中的任何方法上编写单元测试。

我尝试在OrderLineDal中使用dispose方法处理它,一旦我得到了名为dispose的数据。这在第一次迭代中运行良好,但是接下来的30秒,它会说已经丢弃了entityObject并且无法使用。 (对我来说没有意义,因为我每次都要创建一个新的?)

有没有办法可以实现这个存储库模式并仍然处理所有新的entityObjects所以我可以模拟DAL进行单元测试?

我正在使用EF 4.并且它没有设置Code First,所以我没有POCO。

1 个答案:

答案 0 :(得分:1)

理想情况下,您需要在OrderBLL之外创建上下文(搜索谷歌搜索存储库模式)。

public class OrderRepository : IOrderRepository, IDisposable
{
    private readonly IOrderDBContext _dbContext;
    // poor mans dependency injection
    public OrderRepository() : this(new OrderDbContext("YourConnectionString")
    {}

    public OrderRepository(IOrderDBContext dbContext)
    {
        if (dbContext == null) throw new ArgumentNullException("dbContext");
        _dbContext = dbContext;
    }

    public bool GetNewOrders(){
        return _dbContext.Orders.Where(o => o.IsNew==true);
    }

    public void Dispose()
    {
      if (_dbContext != null) _dbContext.dispose();
    }
}

public class OrderBLL : IOrderBLL
{
    private readonly IOrderRepository _repository;

    public OrderRepository(IOrderRepository repository)
    {
        if (repository == null) throw new ArgumentNullException("dbContext");
        _repository = repository;
    }

    public bool HasNewOrders(){
        var newOrders = _repository.GetNewOrders();
        if (newOrders==null) return false;
        return newOrders.Count() > 0;
    }

}


[Test]
public void HasNewOrders_GivenNoNNewOrdersRetunedFromRepo_ReturnsFalse()
{
  // test using nunit and nsubstitute

  // Arrange
  var repository = Substitue.For<IOrderRepository>();
  var emptyOrderList = new List<Order>();
  repository.GetNewOrders().Returns();
  var orderBLL = new OrderBLL(repository);
  // Act
  var result = orderBLL.HasNewOrders();
  // Assert
  Assert.Equals(false, result);
}

现在,您可以将您的上下文注入此类,并轻松测试您的业务逻辑。最终,您将需要创建dbContext,并且还应始终公开它。我建议看一下像Fort Windsor这样的DI容器来管理对象的生命,虽然在服务中你可能只想手动创建和处理你的上下文尽可能靠近代码入口点(例如在主要的方法)