【问题标题】:Should Unit Tests test against the REST API?单元测试是否应该针对 REST API 进行测试?
【发布时间】:2019-01-23 06:44:21
【问题描述】:

现在我已经对我的业务逻辑与 REST Api 层分开进行了单元测试。
在集成测试中,我已经针对它的 api 测试了服务本身。

当然,集成测试不包括单元测试包括的所有边缘情况。感觉就像是矫枉过正和重复的测试代码

但事实上,我还剩下一整层没有被覆盖。我不能确定返回值是否按预期序列化,错误代码是否正确,或者参数是否按我的意愿反序列化。

我的问题是,我应该放弃通过实现它们的对象来测试业务逻辑,而是通过服务进行测试,以便在不重复工作的情况下合并所有案例吗?

注意事项:

  • 我并不是说要放弃所有的单元测试。不直接接触 API 层的足够复杂的单元仍应单独测试。
  • 测试运行时在这里不是问题。

更新

添加了一些示例伪代码以澄清

class Book:
  id: int
  title: string


class BookRepository:
  add_book(book: Book) -> Book
  remove_book(id: int) -> bool
  all() -> List[Book]


class BookApi:
  repository = BookRepository()

  @route('/api/books')
  get() -> List[Book]

  @route('/api/books/id', method=POST)
  add(request_body) -> bool :
    book = parse_book_from_request(request_body)
    return repository.add(book)

  @route('/api/books/id', method=DELETE)
  delete() -> bool

【问题讨论】:

  • 您能否提供一些代码示例,用于这两个部分(业务代码和 REST Api)?
  • @DirkHerrmann 我添加了一个简单的示例来说明分离。我希望很清楚。 Api 负责解析请求,然后发生业务逻辑

标签: unit-testing testing


【解决方案1】:

根据你的描述,我看到的情况如下:

您有两个单元测试场景,即业务逻辑的单元测试和 REST 层的单元测试。您还有一个交互测试场景,即 REST 层和业务逻辑之间的交互。并且,你有一个子系统测试场景,即REST层和业务逻辑共同组成的子系统的测试。

而且,您担心解决所有这些测试场景可能导致的工作量和潜在冗余。 (嗯,实际上你只提到了业务逻辑单元测试和集成测试,所以我可能会让它变得更糟......)

在这里可以帮助您的是针对这些测试场景中的每一个询问自己,哪些错误可能仍然存在而其他测试尚未解决。如果您想到了一个测试用例,但又想不出测试可能检测到的任何错误,则可能不需要该测试用例,或者它的目的已经以其他方式解决了。

从下到上:您对业务逻辑进行了单元测试。那么,哪些单元测试对 REST 层有意义?您提到了反序列化,但也可能会进行合理性检查和对格式错误的请求的处理。所有这些都需要彻底的测试——包括出于安全原因的负面测试。考虑一下您可以在隔离的 REST 层中找到的错误 - 这些显然不是由隔离的业务逻辑的单元测试发现的。

现在,进入交互测试(也称为集成测试):这些测试的目标仅在于各个部分之间的交互,而不是任何一方事后是否做了正确的事情(通过单元测试进行了测试)。换句话说,测试检查是否以正确的顺序和正确的格式使用参数调用正确的函数 - 或者更一般地说,如果接口的双方具有相同的理解。边界情况在这里也很有意义 - 例如查看被调用者是否可以处理调用者提供的极端情况。诚然,如果组件之间的接口与组件大小相比较大,则此处存在冗余风险。

但是,您可以通过某些方式限制冗余:假设您的 REST 层旨在过滤掉无效的 book_id 值。您想测试 REST 层将传递的最大 book_id 是否被业务逻辑接受。如果业务逻辑本身检查book_id,并且如果它不被接受,则抛出异常,您的交互测试可以关注是否抛出异常。您不必验证是否找到了正确的书 - 这是在对业务逻辑进行单元测试时进行测试的。

然后,子系统测试:再次考虑哪些错误可能没有被发现,只有在查看整个子系统时才能发现。例如,子系统是否满足所有要求或是否忘记了某些功能? (单元测试不会发现被遗忘的功能,交互测试可能会——但不是在所有情况下。)是否存在测试可以识别的版本不匹配?并且,再次尝试将测试集中在基本方面,以避免单元测试和交互测试的冗余。

抱歉,我只能用抽象的例子给出一些抽象的建议。

【讨论】:

  • 谢谢,这是我所期望的抽象答案,非常棒。我想我知道在每个测试中要测试什么。我可以使用 json 对象测试 REST 层,并验证输入是否正确发送到业务对象。在测试业务逻辑时,我可以使用对象及其不同的边缘案例来测试逻辑本身。
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-05
  • 2014-10-01
  • 2018-03-19
相关资源
最近更新 更多