你如何单元测试亚音速懒惰加载属性?

时间:2009-03-27 18:24:08

标签: unit-testing orm subsonic tdd

假设我有以下要测试的功能:

public void CancelOrder(Order order)
{
    order.Status = "Cancelled";

    _emailService.SendEmail(order.User.Email, "Your order has been cancelled!");
}

现在,Order类是一个SubSonic生成的类,其上的User属性是延迟加载的,这意味着当我调用order.User.Email时,它实际上运行一个SQL语句来获取用户。

如果我想对此进行单元测试,我会遇到问题,因为我不希望我的单元测试到达我的数据库。

我目前的解决方案是将CancelOrder函数重构为:

public void CancelOrder(Order order)
{
    order.Status = "Cancelled";

    User user = _userRepository.GetByUserID(order.UserID);

    _emailService.SendEmail(user.Email, "Your order has been cancelled!");
}

然后我可以存根_userRepository.GetUserByID()调用以返回硬编码的User对象。

这是最好的方法吗?我想你可以说第二个实现更干净,因为所有数据访问都是通过存储库完成的,而不是隐藏在属性中。

2 个答案:

答案 0 :(得分:0)

定义您自己的类似订单的界面,它提供您需要的简单功能,并将其用作CancelOrder方法的参数类型:

interface Order {
  public void Status(...); // or property
  public string UserEmail():
} 

然后创建该接口的委托实现,例如SubsonicOrder,调用数据库。在测试中使用存根实现。我意识到你可能需要一个更丰富的Order接口模型;这只是一个例子。

如果需要,请对电子邮件服务进行相同操作(可能通过构造函数或服务定位器依赖注入)。

答案 1 :(得分:0)

为什么不希望您的设备测试到达您的数据库?如果您使用MBUnit编写测试用例,则可以使用RollBack属性标记单元测试,并且将回滚对数据库的任何更改。

我一直希望编写以业务层为目标的单元测试用例,但实际上ping数据库,以便单元测试与应用程序本身将使用的最相似。