使用 Jest 进行测试的共享 utils 函数

Posted

技术标签:

【中文标题】使用 Jest 进行测试的共享 utils 函数【英文标题】:Shared utils functions for testing with Jest 【发布时间】:2018-10-28 22:02:55 【问题描述】:

我在各种 Jest 测试中使用了一些 utils 函数,例如这样的函数,用于模拟获取响应:

export const mockFetchJsonResponse = (data) => 
    ok: () => true,
    json: () => data
;

我想以一种可以导入它们并在我的测试中重复使用的方式共享这些函数。例如:

// Some .spec.jsx file
// ...
import mockFetchJsonResponse from 'some/path/to/shared/tests/utils.jsx'

// Then I can use mockFetchJsonResponse inside this test
// ...

这些常用的utils函数应该放在哪里?

我的项目文件夹如下所示:

components/
    CompOne/
        __tests__
        index.jsx
    CompTwo/
        __tests__
        ...
utils/
    __tests__
    http.js
    user.js
    ...

我应该将它们与我在项目中使用的其他 utils 函数一起放在 utils 文件夹中吗?那么我是否也应该为这些功能编写单元测试?

【问题讨论】:

【参考方案1】:

可以将帮助程序公开为全局函数,而无需显式导入模块。

    Jest 允许配置一些文件将在每个通过setupFiles 配置选项执行的测试文件之前运行 Jest 还提供了 global 对象,您可以对其进行修改,并且您在其中放置的所有内容都将在您的测试中可用。

示例

package.json:

"jest": 
    "setupFiles": ["helpers.js"]
 

helpers.js:

global.mockFetchJsonResponse = (data) => 
    ok: () => true,
    json: () => data
;

somecomponent.test.js:

mockFetchJsonResponse(); // look mom, I can call this like say expect()!

使用 TypeScript

TypeScript 会向cannot find name 'mockFetchJsonResponse' 投诉。您可以通过添加声明文件来解决此问题:

helpers.d.ts:

declare function mockFetchJsonResponse(data: any): any;

创建一个新的 tsconfig.test.json 文件并将该文件添加到 files 部分并扩展您的主 tsconfig:


    "extends": "./tsconfig.json",
    "files": ["./.jest/helpers.d.ts"]

在您的 jest.config.js 文件中,为 ts-jest 添加一个新的全局设置,以便开玩笑地使用您的新 tsconfig 文件:

// ...
globals: 
    "ts-jest": 
         tsconfig: "tsconfig.test.json"
    

// ...

当然,它不会直接回答您“将文件放在哪里”的问题,但这取决于您。您只需要在 setupFiles 部分中指定这些文件。由于测试中不需要import,这并不重要。

至于测试测试助手,我不确定。看看它是测试基础设施的一部分,比如规范文件本身。而且我们不会为测试编写测试,否则它永远不会停止。当然,这取决于您 - 假设背后的逻辑是否真的非常复杂且难以理解。但是如果 helper 提供了过于复杂/复杂的逻辑,会导致测试本身无法理解,你同意吗?

感谢article on testing compoentns with intl。以前从未开玩笑地处理过globals

【讨论】:

ESLint 在我使用这些功能时声称 no-undef。所以我认为最好还是使用import, @AndreySemakin,我认为您可以选择使用 import,但我不确定我是否会说它明确更好。我认为任何减少编写良好干净测试的摩擦和改善开发人员人体工程学的东西最终都定义了更好。这总是取决于项目和团队。就个人而言,我倾向于让测试文件的 linter 设置比应用程序代码更宽松。我也不介意在 .d.ts 文件中定义全局变量。 @D.Patrick 完全有道理。至于我,我更喜欢在测试文件中尽可能严格地保持我的 linter 设置,以确保我不会以错误的方式使用我自己的代码 :) 这就是为什么我更喜欢使用 import 而不是使用 Jest 定义全局变量。 这是我一直在寻找的,并且非常符合 .ts 要求。 @Hubro 我想这个答案主要是因为你编辑了关于 Typescript 的部分。【参考方案2】:

另一种方法是拥有一个测试目录并在其上移动助手。

src/
  components/
  utils/
  ...
test/
  testHelpers.js

然后上测试:

// src/components/MyComponent.spec.js
import  helperFn  from '../../test/testHelpers';

好处:

明确函数的来源 将需要测试的助手与不需要测试的助手分开 ¹

缺点:

test 目录可能看起来很傻,因为它只包含一个帮助文件 AFAIK 官方文档中没有指定这种方法

在他们的 RoR 项目中看起来像 GitLab is implementing 这种方法。

¹无论您采用哪种方法,请不要测试测试助手。如果助手失败,那么您的测试也必须失败。否则你的助手根本没有帮助。

【讨论】:

问题是这些函数会被打包到tests文件夹中。【参考方案3】:

TL;DR;创建/__utils__/ 并更新testPathIgnorePatterns

完整答案:

这里只是一个建议:

testPathIgnorePatterns: ['/__fixtures__/', '/__utils__/'],

我使用/__tests__/ 进行测试,有时我需要在其中添加一个文件夹,其中包含这些测试将使用的数据,所以我使用/__fixtures__/ 文件夹。

同样,当我有一个跨测试共享逻辑时,我将它们放在/__utils__/ 文件夹中(也在/__tests__/ 中)

更多详情,请阅读更多testPathIgnorePatterns

【讨论】:

以上是关于使用 Jest 进行测试的共享 utils 函数的主要内容,如果未能解决你的问题,请参考以下文章

Vue 单元测试 使用mocha+jest

用新的模拟覆盖现有/共享的 Jest 模拟,仅用于一个测试

如何使用 vue-test-utils 和 Jest 在 Nuxt 中对使用 vuex-module-decorators 语法定义的 Vuex 模块进行单元测试?

带有 vue-test-utils 和 Jest 的 Vue.js 单元测试用例失败

Vue 和 Jest 单元测试组件

使用 Jest 进行测试时,classnames_1.default 不是函数