【问题标题】:TDD - How much do you test?TDD - 你测试了多少?
【发布时间】:2009-01-05 03:55:20
【问题描述】:

我正在开发一个新项目,我正在使用存储库模式,我有一个从数据库中提取数据的存储库和一个使用该存储库并执行所有业务逻辑的“服务”类。

类似下面的东西;

public class UserRepository : IUserRepository
{
    public IQueryable<User> GetUsers()
    {
    // do stuff
    }
}

public class UserService 
{
    public IList<User> GetUserById
    {
        var rep = new UserRepository();
        var users = rep.GetUsers();
        // do business logic
        return users.ToList();
    }
}

您会同时测试 UserService 和 UserRepository,还是认为仅测试 Service 就足够了?我认为由于该服务正在使用存储库,它应该很有趣,但它确实会杀死代码覆盖率。

【问题讨论】:

    标签: c# .net unit-testing tdd


    【解决方案1】:

    您应该同时测试它们,因为有一天可能会有除 UserService 之外的其他 UserRepository 客户端,并且这些客户端使用 UserRepository 的方式可能与 UserService 不同。

    【讨论】:

      【解决方案2】:

      测试您需要的功能:

      • 某些功能可能属于一个类
      • 有些可能位于其他类中
      • 有些可能需要两个类

      从您的描述看来,您可以定义功能,因此您几乎可以证明测试任何您喜欢的东西是合理的;-)

      如果您正在寻找最低的 TDD 效率,仅测试当前功能,然后继续代码覆盖率与 TDD 无关;这是一个单元测试指标(价值有问题)

      [让投票开始吧! ;-)]

      【讨论】:

      • “开始投票吧!”我知道你在开玩笑,但我希望事实并非如此。与每个编程方面一样,许多人把它看得太远和太认真了。它不像没有测试某些部分意味着测试有缺陷,它不像测试是检查错误的唯一方法。
      • @[Spodi]:我只是在开玩笑。有些单元测试的拥护者会坚持 100% 的代码覆盖率,包括 getter 和 setter。不过,这不是 TDD 的全部意义......
      【解决方案3】:

      如果您已经编写了代码并且现在才开始考虑测试,那么您已经偏离了测试驱动开发的真正路径 :-) 也就是说,如果是我的代码,我会编写UserService 先测试,然后检查我的代码覆盖率。

      编辑以回应评论:如果您还没有真正编写代码,我会先为UserService 编写测试,因为这是您应用程序的最终目标。然后,当我编写代码以使UserService 测试通过时,我会生成存储库的测试。这些测试最终会成为存储库的规范,以防您以后想重用它。

      【讨论】:

      • 我还没有写代码,我在考虑架构,正准备写测试,不知道我应该写多少
      【解决方案4】:

      您应该同时测试它们。测试完仓库后,再去测试服务会更容易,更可靠。

      【讨论】:

        【解决方案5】:

        这里有两个选择:

        • 单元测试 - 在这种情况下,您在不访问服务、磁盘、数据库、活动目录等的情况下单独测试每个组件。这是通过让您的测试充当驱动程序并存根/模拟所使用的类来实现的按您正在测试的课程。

        • TDD - 这类似于单元测试,但在这种情况下,您将编写测试用例,运行它以使其失败,编写足够的代码使其通过,运行它以确认它通过,然后继续下一个。在这种情况下,所有代码都应该被覆盖。

        在您的情况下,重要的是要意识到在测试 UserService 时,您将针对实现 IUserRepository 的 DummyRepository 对其进行测试。在这种情况下,您可以完全测试用户服务,而无需访问真正的底层存储库类/数据源。这将明确区分两个类中的错误,并使您能够控制模拟存储库的所有可能故障。

        您将执行相同的操作来测试 UserRepository 实现。这是通过排除对底层资源的访问。您可以使用 Mock 框架,它使用分析器 API 来模拟依赖项,或者使用接口/虚拟方法来允许单元测试类覆盖对资源的访问。

        除了上面的白盒测试技术,你还需要做你的黑盒/集成测试。这就是你有一些端到端测试用例的地方,它们作为一个整体测试应用程序场景,其中 UserService 与 UserRepository 交互,然后与数据源交互。

        【讨论】:

          【解决方案6】:

          如果您遵循 TDD 流程 - 正如问题标题所暗示的那样 - 如果没有经过测试,您将不会同时拥有 UserRepository 和 UserService 类。

          有一句极限编程说:“测试所有可能破坏的东西”,所以你最好对它们都进行测试,这样你才能对你的代码充满信心。

          【讨论】:

            【解决方案7】:

            正如其他人已经提到的,如果 UserService 是您的应用程序的客户端将要看到的全部内容,那么我现在只对其进行测试,并使您的客户端无法访问 UserRepository(例如,将其设置为内部)。这样,即使不单独测试类,您也应该获得良好的代码覆盖率。

            如果您的代码覆盖率不好,这通常意味着您的测试不充分,或者您实现了无法通过公共接口调用的内容,因此可能会被删除。

            【讨论】:

              【解决方案8】:

              通过模拟存储库来编写服务单元测试,以测试服务中的业务逻辑并测试不同的存储库场景,如异常、测试返回值等。一些模拟框架(如 EasyMock)需要存储库接口,而其他模拟框架(如 Mockito)则不需要。这样您的服务测试将不会访问数据库并且执行速度会更快。

              编写存储库测试以测试您的所有数据库交互。使用 DB 单元数据集/fixtures 测试数据,以确保您的 DB 逻辑正确实现。

              此外,您可能希望在无需模拟存储库的情况下访问数据库的服务类上编写集成测试。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-08-26
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多