单元测试时模拟外部库的方法有什么意义?

时间:2019-06-20 02:06:04

标签: javascript node.js unit-testing testing

在进行单元测试时,模拟外部库的方法有什么意义?

假设我有一个函数,该函数使用XYZ库使用给定的授权令牌来获取当前用户,然后,如果找到该用户,它将返回一个有效的AWS策略:

export const getUser = async token => {
  const user = await XYZ.getUser(token)
  return {
    // valid policy
    context: user,
  }
}

如果给出了无效的令牌,则getUser应该抛出错误。

  • 如果XYZ.getUser已被良好测试,那么测试该功能有什么意义?
  • 为什么要模拟getUser而不使用真实的?

2 个答案:

答案 0 :(得分:0)

由于以下原因,您不想为XYZ.getUser(token)调用实际的HTTP请求。

1)单元测试的目的是测试特定的行为,在您的情况下,它是测试getUser函数是否确实有效。

2)您不想向后端发出实际请求,因为这通常意味着从数据库中写入/读取/删除某些内容。在许多情况下,使单元测试过于复杂不是一个好主意,因为此类操作不应在前端进行测试,因为您可能希望限制和简化单元测试以测试特定行为。 >

3)由于主要目的是测试上述行为,因此您希望简化并限制要测试的内容。因此,您需要了解XYZ.getUser(token)的网络请求的单元测试应该在服务器端而不是客户端(或前端)进行。

4)通过模拟来自XYZ.getUser(token)的响应,我们可以模拟多个场景和响应,例如成功的响应(代码200 OK)以及其他类型的错误(来自后端的业务逻辑错误或网络错误)例如错误400、500等)。为此,您可以根据需要测试的不同类型的场景,对来自XYZ.getUser(token)的必需JSON响应进行硬编码。

答案 1 :(得分:0)

这可以追溯到单元测试的定义和用法。

单元测试应该可以测试定义良好的功能,例如,您可以编写算法,并且该功能的定义非常明确。然后,因为您知道它的工作原理,所以您将对其进行单元测试。

按定义,单元测试并不意味着要接触任何外部系统,例如但不限于文件,API,数据库,以及任何需要超出逻辑单元(即您要测试的代码)的东西。

原因有很多,其中包括执行速度。调用API或使用第三方调用需要一段时间。当您查看一个测试时,这不是必需的问题,但是当您进行500个或更多测试时,延迟将很重要。主要思想是,您应该一直在快速运行单元测试,您会立即获得反馈,这有什么坏处,如果我在系统的其他部分坏了。在任何成熟的系统中,您都将在CI / CD流程中运行这些测试,并且您不能等待太久才能完成测试。不,它们需要在几秒钟内运行,这就是为什么您要了解它们应该或不应该接触的规则。

因为您只想测试自己的代码,所以您可以嘲笑外部事物,以提高执行速度并消除第三方问题。

如果您调用第三方API且无法维护,该怎么办?这是否意味着因为它们而导致您无法测试代码?

现在,关于模拟的主题,不要过多地使用它,如果您以功能性方式进行编码,则可以消除大量模拟的需要。传递数据而不是传递或har-coding依赖项。这样就很容易更改输入数据而无需进行太多模拟。您可以在使用集成/端到端测试时对系统进行测试,这可以确保您的依赖关系已正确解决。