如何将 Jest 模拟函数的范围限制为单个测试

2024-02-02

我正在使用 Jest + 测试库/React 编写功能测试。经过几天的绞尽脑汁,我发现当你使用.mockResolvedValue(...) or .mockResolvedValueOnce(...)嘲笑的范围不仅限于该测试......

import React from "react";
import { render, waitForElement } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import myApi from '../myApi';
jest.mock('../myApi'); // this will load __mocks__/myApi.js (see below)
import { wait } from '@testing-library/dom';
import App from "../components/App";

afterEach(() => {
  jest.clearAllMocks();
});


describe("App", () => {

    test("first test", async () => {

        myApi.get.mockResolvedValueOnce('FOO');

        // App will call myApi.get() once
        const { container, getByText } = render(<App />);

        await waitForElement(
            () => getByText('FOO')
        );

        expect(myApi.get).toHaveBeenCalledTimes(1);

        // This is going to "leak" into the next test
        myApi.get.mockResolvedValueOnce('BAR');

    });

    test("second test", async () => {

        // This is a decoy! The 'BAR' response in the previous test will be returned
        myApi.get.mockResolvedValueOnce('FOO');

        // App will call myApi.get() once (again)
        const { container, getByText } = render(<App />);

        // THIS WILL FAIL!
        await waitForElement(
            () => getByText('FOO')
        );

        expect(myApi.get).toHaveBeenCalledTimes(1);

    });


});

这是什么__mocks__/myApi.js好像:

export default {
  get: jest.fn(() => Promise.resolve({ data: {} }))
};

我明白发生了什么:myApi被导入到两个测试的共享范围中。这就是为什么.mockResolvedValue*适用于“跨”测试。

防止这种情况的正确方法是什么?测试应该是原子的,并且不能相互耦合。如果我触发另一个get请求在first test它不应该被打破second test。太臭了!但什么是正确的模式呢?我正在考虑克隆不同的“副本”myApi进入本地测试范围......但我担心这会变得奇怪并导致降低我的测试的信心。

I found 这个问题 https://stackoverflow.com/questions/46855281/scoping-in-jest-when-mocking-functions它讨论了相同的主题,但仅解释了为什么会发生这种情况,而不是讨论避免这种情况的正确模式。

包.json

  "dependencies": {
    "axios": "^0.18.1",
    "moment": "^2.24.0",
    "react": "^16.11.0",
    "react-dom": "^16.11.0",
    "react-redux": "^7.1.3",
    "react-router-dom": "^5.1.2",
    "react-scripts": "2.1.5",
    "redux": "^4.0.4",
    "redux-thunk": "^2.3.0"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^4.2.3",
    "@testing-library/react": "^9.3.2",
    "redux-mock-store": "^1.5.3",
    "typescript": "^3.7.2"
  }

这就是我构建测试的方式:

  • Having a beforeAll block in the beginning of the test suit for
    • 设置模拟
    • 清除即将测试的mock函数
    • 渲染组件
    • 调用函数
  • Writing separate test cases each described in own test/it block
    • 让每个人都有更好的、单独的描述
    • 更好地了解失败的地方--verbose mode

example:

App.spec.js
describe("App", () => {
  // jest allows nesting of test suits
  // allowing us to have prettier reporting
  // and having scoped variables
  describe("Api.get returning FOO", () => {
    // define variables used in the test suit
    let wrapper;
    // having the setup here
    beforeAll(async () => {
      Api.get.mockClear();
      Api.get.mockResolvedValue("FOO");
      const { container, getByText } = render(<App />);
      // expose the container to the scope
      wrapper = container;

      await waitForElement(() => getByText("FOO"));
    });

    // write the test cases balow
    // each assertion in a separate test block
    test("should call the Api once", () => {
      expect(Api.get).toHaveBeenCalledOnce();
    });

    test("should have been called with data", () => {
      expect(Api.get).toHaveBeenCalledWith({ x: "y" });
    });

    test("should match the snapshot", () => {
      expect(wrapper).toMatchSnapshot();
    });
  });

  describe("Api.get returning BAR", () => {
    // define variables used in the test suit
    let wrapper;

    beforeAll(async () => {
      Api.get.mockClear();
      Api.get.mockResolvedValue("BAR");
      const { container, getByText } = render(<App />);
      // expose the container to the scope
      wrapper = container;

      await waitForElement(() => getByText("FOO"));
    });

    test.todo("describe what is supposed to happen with Api.get");
    test.todo("describe what is supposed to happen container");
  });
});

回到问题 - 是的,模拟函数将在整个测试文件中使用,但是如果你有mockResolvedValueOnce尚未消耗(泄漏到下一个测试中)的上述测试用例之一将失败,或者您的测试编写得很糟糕。


Edit:

作为一个思想实验,你能想出一个可以“解决”这个问题的结构吗?

要在每次测试后删除返回模拟值和实现,您可以使用

afterEach(() => {
  jest.resetAllMocks()
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 Jest 模拟函数的范围限制为单个测试 的相关文章

  • 使用 Jest 监视链式方法调用不起作用

    我已经定制了自己的习惯TextInput组件需要一个nextField支柱 当我的 完成 按钮TextInput被按下时 nextField应该集中精力 很简单 它在生产中起作用 但是 我在测试重点代码行时遇到了问题nextField th
  • LocalDate 与属性占位符 Spring

    我正在使用 Spring Boot 和属性占位符 我有一个属性文件 其值为 date A 24 07 17 我有一堂课 我正在使用 Value注解 Value date A private LocalDate dateA 但我在运行时遇到运
  • Jest moduleNameMapper 查找文件:“resolver”:未定义

    我有一个文本文件 除其他外 component路径下的文件夹 src components text 但是 当 webpack 别名为 Jest 时 Jest 找不到这个文件import Text from components text
  • 如何模拟类路径上属性文件的存在?

    这肯定是一个常见问题 我有一个像这样的属性文件my settings properties由应用程序类读取 当我编写测试类时 它需要测试可能存在的不同场景my settings properties为了确保最大的代码覆盖率 例如空属性文件
  • Grails 测试中的模拟配置

    在 Grails 2 0 X 之前 可以使用mockConfig测试扩展的基类提供的方法 然而 在 Grails 2 0 X 中 建议测试类使用 TestFormixin 而不是扩展基类 这个 mixin 似乎没有提供任何与mockConf
  • C# 压力测试 - 模拟对给定共享资源的多次访问

    如何在 C 单元测试中模拟 压力测试 100 个用户访问给定的共享资源 例如数据库 假设您正在访问真实的数据库 那么您就处于集成测试的范围内 最简单的方法是从多个线程访问资源 例如 Test public void SimpleStress
  • Android:如何测试自定义视图?

    Android 中有多种单元测试方法 测试我编写的自定义视图的最佳方法是什么 我目前正在将其作为仪器测试用例活动的一部分进行测试 但我宁愿只测试孤立的视图 对于缺乏以视图为中心的测试用例实现的一个简单解决方案是在包含视图的测试项目中创建一个
  • 单元测试:独立测试与代码重复(DRY)

    我正在迈出单元测试的第一步 并且不确定在单元测试中似乎相互矛盾的两个范式 即 每个单元测试都应该是独立的 不依赖于其他单元测试 不要重复自己 更具体地说 我有一个要测试的导入器 导入器具有 导入 功能 获取原始数据 例如 从 CSV 中取出
  • 测试 Spring 端点时如何防止 NestedServletException?

    我在尝试着测试安全配置我的一些端点受到保护 PreAuthorize oauth2 hasScope scope 当使用不具有所需范围的访问令牌通过 Postman 访问此类端点时 将返回以下内容并带有 HTTP 状态代码 403 禁止 e
  • 如何获取Azure DevOps Pipelines中变量的单元测试结果?

    我在 Azure DevOps 中有一个构建管道 并且正在使用 NET Core 任务来应用单元测试 我需要获取变量中单元测试的结果 例如 如果有 10 个测试用例 其中两个失败 我需要得到如下信息 failedTestCases 2 su
  • PHPUnit - 使用配置文件时“未执行测试”

    问题 为了提高代码质量 我决定尝试学习如何使用单元测试来测试我的代码 而不是使用平庸的最佳测试解决方案 我决定使用 Composer 安装 PHPUnit 作为个人库 它可以让我实现常见的数据库功能 起初我没有 PHPUnit 的配置文件
  • 是否有用于运行测试组的 JUnit TestRunner?

    我目前正在使用 JUnit 4 并且需要将我的测试分为可以以任意组合有选择地运行的组 我知道 TestNG 具有注释测试以将它们分配到组的功能 但我现在无法迁移到 TestNG 看来这可以通过一些自定义注释和自定义 JUnit TestRu
  • 使用带有 OnException 定义的adviceWith进行Camel路由测试

    我有一个非常简单的 Camel 路由定义 其中只包含一些 OnException 谓词来处理相应的异常和一些日志语句 from hazelcast seda someQueue id someQueueID onException Cust
  • CSV 提供的数据源第一列中存在奇数字符

    我有一个 CSV 文件 已添加到 Visual Studio 单元测试项目中 它有七列 如下所示 assessmentitemid reviewer1 reviewer2 reviewer3 reviewer4 reviewer5 revi
  • 如何在 Jenkins 服务器上运行 Jest 测试

    我正在尝试运行我的Jest https facebook github io jest 在 Jenkins 部署期间进行测试 如果我 ssh 进入服务器 我可以 sudo 进入 Jenkins 用户并从工作区成功运行测试 但是 当我尝试从
  • 如何对嵌套函数进行单元测试? [复制]

    这个问题在这里已经有答案了 您将如何对嵌套函数进行单元测试f1 在下面的例子中 def f def f1 return 1 return 2 或者需要测试的函数不应该嵌套吗 有一个类似的问题这个链接 https stackoverflow
  • 使用 Retrofit2 和 Mockito 或 Robolectric 进行 Android 单元测试

    我可以测试 Retrofit2beta4 的真实响应吗 我需要 Mockito 或 Robolectic 吗 我的项目中没有活动 它将是一个库 我需要测试服务器是否正确响应 现在我有这样的代码并卡住了 Mock ApiManager api
  • 从文件夹中删除文件的单元测试方法

    我们有一个方法 它将文件夹名称和天数作为参数 public void Delete string folder int days var files Directory GetFiles folder foreach var file in
  • Coffeescript + 单元测试:全局变量?

    我正在尝试使用 Jasmine 对用 CoffeeScript 编写的小型应用程序进行单元测试 我发现很多资料都说单元测试可以在从 CoffeeScript 编译的 JS 上完美地完成 如果所有内容都包装在匿名函数中以避免污染名称空间 如何
  • Xcode 异步单元测试在主线程上等待

    我正在尝试使用 Xcode 中的单元测试来测试一些异步代码 但主线程被阻塞 问题在于 某些正在测试的代码期望从 iOS 类 AVFoundation 接收回调 但是 AVFoundation 类似乎只会在主线程上回调 问题是 如果我正在进行

随机推荐

  • 图例中的刻度尺寸符号

    我绘制了一个气泡图 http www r bloggers com wp content uploads 2010 12 bubbleChart png圆圈的大小对应于使用 matplotlib 的值列表 但是 我在为具有与列出的大小相对应
  • 从字符串中分割货币和金额

    我正在导入一个包含不同货币符号的金额的文件 12 10 26 13 12 50 我需要将其导入并转换为单一货币 我将字符串拆分如下 parts split preg replace 0 9 1 amount 1 无法使 preg split
  • Android中文件、类和活动之间的区别

    Android中的文件 类和活动有什么区别 文件 它是任意信息块或用于存储信息的资源 它可以是任何类型 类 它是 Java 文件的编译形式 Android最终使用这个 class文件生成可执行的apk 活动 活动相当于 GUI 工具包中的框
  • 禁用 Django 中特定应用程序的本地化

    有没有办法在 Django 设置中禁用特定应用程序的本地化 造成这种情况的可能原因有两个 关闭管理应用程序 例如 contrib admin 中的本地化 因为管理员更喜欢使用英语而不是本地语言 一些应用程序的默认翻译确实很糟糕且令人困惑 我
  • React 16:使用钩子和功能组件时从父级调用子级函数

    我需要在父组件中调用子组件的函数 我该怎么做呢 之前在 React 15 中 我可以使用 refs 来调用子函数 但不知道如何使用钩子和功能组件来做到这一点 function Child props function validate to
  • 如何将验证器与 QTableWidgetItem 一起使用?

    假设我有一个 QTableWidgetItem 项目 我只想验证用户输入的数据 例如 用户仅在该项目中输入数字 否则程序将显示警告对话框 我也搜索该文档页面 http harmattan dev nokia com docs library
  • 改进 AngularJS 指令代码

    我写了一个 AngularJS 指令 但我对它还很陌生 我不知道我是否以 Angular 方式 完成 这是我的代码 http plnkr co edit X1tOk4z8f6dCK3mfB7HP p preview http plnkr c
  • 没有事务的 JTA 数据源

    假设手动登记和取消资源 我有许多启用 XA 的资源 数据源 我计划对其执行事务更新 此外 一些支持 XA 的数据源可以单独更新 不需要任何其他资源 假设我已经使用登记的数据源提交了多个事务 那么我可以忽略 TransactionManage
  • JMS 客户端工具 - Java 8 的 HermesJMS 的替代品吗?

    HermesJMS 有哪些替代方案 我需要针对 JBoss WildFly 8 进行测试 它使用 Java 8 HermesJms 似乎是为 Java 6 构建的 但我找不到完整的 Java 8 端口 我尝试设置 hermes bat这个配
  • iPhone iOS 如何将 UILongPressGestureRecognizer 和 UITapGestureRecognizer 添加到同一个控件并防止冲突?

    我正在构建一个 iPhone 应用程序 它可以让用户重新排列屏幕上的一些 UI 元素 如何将点击手势识别器和长按手势识别器添加到同一个 UIView 中 当我长按抬起手指时 点击手势识别器就会启动 如何暂时禁用点击手势识别器或防止其在用户长
  • 在 ASP.NET 中使用 Web API 相对于 Web 方法有什么优势

    我熟悉网络方法 现在我收到了使用 Web API 而不是 Web 方法的建议 我做了一个 ASP NET Web API 的演示 它更接近于MVC架构我正在使用经典的 ASP NET Web 开发 我不喜欢搞乱控制器 MVC概念 采用经典开
  • 警告:mysqli_connect():(HY000/2002):尝试以访问权限禁止的方式访问套接字

    这两天我一直在尝试解决这个问题 警告 mysqli connect HY000 2002 尝试以访问权限禁止的方式访问套接字 我的托管是Azure 他的界面非常糟糕 编程语言是PHP 我的数据库与域位于同一资源组中 帐户数据是正确的 我做错
  • 网络中的边长x

    我正在尝试通过以下代码调整两个节点之间的边的长度 但显然这不起作用 谁能指导我在哪里犯了错误 请注意 我已经看过这个帖子了 如何在 Networkx 中指定边长度来计算最短距离 https stackoverflow com questio
  • 如何在 Android Jelly Bean Launcher 中添加自定义视图

    我正在努力在 android 中制作自定义启动器 我参考了android的Jellybean启动器的代码 现在我想对这个启动器进行一些修改 我想要的是 据我们所知 默认有五个工作区屏幕 我想在任何一个工作区屏幕中添加自定义视图 我的 xml
  • 从数据库中提取行(包括相关行)

    我想为 Oracle 数据库中的一行生成插入字符串 包括其他表中的所有依赖行 及其依赖行 Example CREATE TABLE a a id number PRIMARY KEY name varchar2 100 CREATE TAB
  • PDO + MySQL 和损坏的 UTF-8 编码 [重复]

    这个问题在这里已经有答案了 我在 PHP 中将 PDO 库与 MySQL 数据库一起使用 但是如果我插入任何以 UTF 8 编码的数据 例如阿拉伯单词 它就会插入到数据库中 但作为 在我自己的框架中 创建 PDO 连接后 我发送两个查询 S
  • Solr:结合 EdgeNGramFilterFactory 和 NGramFilterFactory

    我有一种情况需要同时使用 EdgeNGramFilterFactory 和 NGramFilterFactory 我正在使用 NGramFilterFactory 执行 包含 样式搜索 最小字符数为 2 我还想搜索第一个字母 例如带有前面
  • 如何通过蓝牙查询远程手机是否支持PBAP?

    假设两部Android手机通过蓝牙配对并建立连接 如何在客户端以编程方式确定远程设备 服务器 是否支持蓝牙配置文件 例如 PBAP 如果它确实支持 那么如何以编程方式启动与远程设备的 PBAP 会话 我在网上进行了广泛的搜索 但到目前为止还
  • Apache Flink:设置并行度的指南?

    我正在尝试获取一些简单的规则或指南来设置哪些值 操作员或工作 并行性 在我看来 它应该是一个数字 例如 假设我有 2 台任务管理器机器 每台都有 4 个任务槽 假设集群上没有运行其他作业 我会设置并行度吗 用于操作 喜欢过滤并映射到 8 如
  • 如何将 Jest 模拟函数的范围限制为单个测试

    我正在使用 Jest 测试库 React 编写功能测试 经过几天的绞尽脑汁 我发现当你使用 mockResolvedValue or mockResolvedValueOnce 嘲笑的范围不仅限于该测试 import React from