服务上的单元测试是否有意义?

时间:2016-04-02 12:41:09

标签: java spring unit-testing layer

我正在Java Spring中编写一个由图层组成的应用程序。他们的责任是:

  • REST / Controller层 - 根据请求处理传入请求,用户身份验证,解析请求主体以及与Service层通信
  • 服务层 - 主要处理创建/编辑/删除实体之间的关联和状态。与DAO层和“实用程序”进行通信
  • DAO层 - 持久性,将保存/删除/查找请求的实体
  • 实体/对象? layer - 表示应用程序域的对象,相当愚蠢的功能,主要用于跟踪关联
  • “实用程序”图层 - 实际上不是图层,提供检查对象之间权限的服务(对象A想要将对象B添加到对象C,因为它需要权限XYZ ...)等等。

我在开发过程中一直在编写一些测试,现在我已经考虑过了,它们已经进行了一些集成测试。测试的一般流程可以描述为:

  1. 调用serviceX以创建对象A
  2. 调用serviceX以创建对象B
  3. 调用serviceY对对象A和B执行某些操作
  4. 调用serviceX报告对象A和B的状态,并检查一切是否正确
  5. 在每个步骤中,服务调用DAO层和保存/创建/获取的对象,然后对其进行操作,如果操作成功并且符合预期,则检查测试。

    我正在考虑如何正确地进行单元测试。我知道我应该模拟测试服务所依赖的每个组件,这样我就可以“隔离”我想要测试的行为。但是,大多数服务方法实际上并没有“返回”任何东西,它们只是操纵实体。

    我遇到的问题是 - 总是对应用程序的单元测试层/服务有意义,还是可以将它们作为一个整体进行测试?

    附录

    其中一种方法的示例。这个负责向组添加新用户。添加成员必须由该组的经理完成。所以逻辑是:

    • 获取参数 - manager,group,newUser
    • 如果任何参数为null,则抛出异常
    • 致电UIImage服务并检查permissionHandler用户是否在manager中拥有足够的权限才能完成此操作
    • 检查组中是否已存在group。如果是,请抛出异常。
    • 如果一切正常,请致电newUser服务以创建一个新的groupMemberHelper对象,表示GroupMemberuser之间的关联(以及有关该关联的更多信息)
    • 将此group对象添加到论坛
    • 对于该组已拥有的所有“项目”,请调用帮助程序服务,该服务在这些项目与新添加的用户之间创建链接。

    为了测试这个方法,我会跟踪GroupMembergroup以及此方法影响的所有对象,并检查状态“之前”和“之后”是否是我期望的状态

    在不依赖被调用服务的功能的情况下,我想不出另一种测试方法。我错了吗?

2 个答案:

答案 0 :(得分:2)

示例中的方法向您显示您在服务中做了很多事情。这就是副作用所做的测试 - 他们展示了弱代码架构。尝试将验证逻辑移动到另一个bean,创建逻辑到工厂等等。您将拥有易于阅读,理解,维护和单元测试的代码。

答案 1 :(得分:2)

  

我知道我应该模拟测试服务所依赖的每个组件,以便我可以“隔离”。我想测试的行为。

这种广泛持有的观点是错误的。您总是必须模拟每个协作者。

在测试我的表示层时,我使用模拟数据层和真实(非模拟)服务层。

广泛持有的观点的错误是指定的行为和实现细节之间存在差异。您的测试应该测试指定的行为。他们不应该假设任何特定的实现细节。在大多数情况下,除了它的调用满足下层所施加的任何先决条件之外,没有指定高层与下层交互的方式。因此,如果您使用模拟的下层测试更高层,则模拟必须为其方法的每个提供正确的行为,因为您不知道更高层将调用哪些方法。这可以使正确的模拟对象与真实对象一样复杂。在这种情况下,使用模拟可以获得任何收益。

模拟数据层不是太繁重,因为您可以使用地图和列表而不是数据库将其实现为内存存储,并对所有服务层和表示层测试使用相同的模拟类。 / p>