【问题标题】:How do you unit test Subsonic lazy-loaded properties?您如何对 Subsonic 延迟加载属性进行单元测试?
【发布时间】:2009-03-27 18:24:08
【问题描述】:

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

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() 调用以返回硬编码的用户对象。

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

【问题讨论】:

    标签: unit-testing orm subsonic tdd


    【解决方案1】:

    定义您自己的类似 Order 的接口,该接口提供您需要的基本功能并将其用作 CancelOrder 方法的参数类型:

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

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

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

    【讨论】:

      【解决方案2】:

      您为什么不希望您的单元测试访问您的数据库?如果您使用 MBUnit 编写测试用例,您只需使用 RollBack 属性标记单元测试,对数据库的任何更改都将回滚。

      我一直更喜欢编写针对业务层但实际上 ping 数据库的单元测试用例,以便单元测试与应用程序本身将使用的最相似。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-04-20
        • 1970-01-01
        • 1970-01-01
        • 2020-06-01
        • 2017-09-11
        • 1970-01-01
        • 2019-09-16
        相关资源
        最近更新 更多