如何在 redux 操作(或操作中分配的其他回调)上下文中使用 jest 测试 `image.onload`

2023-11-26

我的问题是我正在尝试对一个函数进行单元测试,但不知道如何测试它的一部分。

这是一个 React / Redux 操作,执行以下操作:

1) 使用图像 url 检索 json 数据

2) 将图像加载到 Image 实例中并将其大小分派给减速器(当使用 Image.onload 加载图像时异步)

3) 将获取已完成的信息分派给reducer

图像加载是异步发生的,因此当我尝试对其进行单元测试时,它不会被调用。此外,我不能只是模拟事物,因为图像实例是在函数内创建的......

这是我想要测试的代码(删除一些检查、分支逻辑等):

export function fetchInsuranceCardPhoto() {
    return dispatch => {
        dispatch(requestingInsuranceCardPhoto());
        return fetch(`${api}`,
            {
                headers: {},
                credentials: 'same-origin',
                method: 'GET',
            })
            .then(response => {
                switch (response.status) {
                    case 200:
                        return response.json()
                            .then(json => {
                                dispatch(receivedInsuranceCardPhoto(json));
                            })
                }
            });
    };
}

function receivedInsuranceCardPhoto(json) {
    return dispatch => {
        const insuranceCardFrontImg = json.insuranceCardData.url_front;
        const insuranceCardBackImg = json.insuranceCardData.url_back;

        if (insuranceCardFrontImg) {
            dispatch(storeImageSize(insuranceCardFrontImg, 'insuranceCardFront'));
        }

        return dispatch(receivedInsuranceCardPhotoSuccess(json));
    };
}

function receivedInsuranceCardPhotoSuccess(json) {
    const insuranceCardFrontImg = json.insuranceCardData.url_front;
    const insuranceCardBackImg = json.insuranceCardData.url_back;
    const insuranceCardId = json.insuranceCardData.id;

    return {
        type: RECEIVED_INSURANCE_CARD_PHOTO,
        insuranceCardFrontImg,
        insuranceCardBackImg,
        insuranceCardId,
    };
}

function storeImageSize(imgSrc, side) {
    return dispatch => {
        const img = new Image();
        img.src = imgSrc;
        img.onload = () => {
            return dispatch({
                type: STORE_CARD_IMAGE_SIZE,
                side,
                width: img.naturalWidth,
                height: img.naturalHeight,
            });
        };
    };
}

注意最后一个storeImageSize私有函数如何创建 Image 实例并将 image.onload 分配给函数。

现在这是我的测试:

it('triggers RECEIVED_INSURANCE_CARD_PHOTO when 200 returned without data', async () => {
        givenAPICallSucceedsWithData();

        await store.dispatch(fetchInsuranceCardPhoto());

        expectActionsToHaveBeenTriggered(
            REQUESTING_INSURANCE_CARD_PHOTO,
            RECEIVED_INSURANCE_CARD_PHOTO,
            STORE_CARD_IMAGE_SIZE,
        );
    });

但该测试将会失败,因为测试在image.onload回调被调用。

我怎样才能强制image.onload调用回调以便我可以测试“STORE_CARD_IMAGE_SIZE”操作是否被广播?


经过一番调查,我发现一个非常有趣的 JavaScript 函数可以解决我的问题。

它是这个:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

这是我的使用方法Object.defineProperty(...)解决我的问题:

describe('fetchInsuranceCardPhoto', () => {
    let imageOnload = null;


    /** Override Image global to save onload setting here so that I can trigger it manually in my test */
    function trackImageOnload() {
        Object.defineProperty(Image.prototype, 'onload', {
            get: function () {
                return this._onload;
            },
            set: function (fn) {
                imageOnload = fn;
                this._onload = fn;
            },
        });
    }

    it('triggers RECEIVED_INSURANCE_CARD_PHOTO when 200 returned with data', async () => {
        trackImageOnload();
        givenAPICallSucceedsWithData();

        await store.dispatch(fetchInsuranceCardPhoto());
        imageOnload();

        expectActionsToHaveBeenTriggered(
            REQUESTING_INSURANCE_CARD_PHOTO,
            RECEIVED_INSURANCE_CARD_PHOTO,
            STORE_CARD_IMAGE_SIZE,
        );
    });

我在这里所做的是使用定义属性来覆盖任何实例的设置器Image。 setter 将继续像平常一样获取或设置,但也会保存在单元测试范围内设置为变量的值(在本例中为函数)。之后,您可以在测试的验证步骤之前运行您捕获的函数。

Gotchas- 需要设置可配置 - 注意defineProperty是一个不同的函数defineProperties- 这在实际代码中是不好的做法。 - 记得使用原型

希望这篇文章可以帮助有需要的开发者!

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

如何在 redux 操作(或操作中分配的其他回调)上下文中使用 jest 测试 `image.onload` 的相关文章

随机推荐

  • 计算 UITextView 中的行数,按帧大小包裹的行数

    我想知道当文本被文本视图的框架包裹时 是否有任何分隔符可以用来识别文本是否被包裹 例如 如果我的文本视图的宽度为 50 px 并且文本超过该宽度 则会将文本换行到下一行 我想计算文本视图中的行数 现在 n 和 r 对我没有帮助 我的代码是
  • 如何使用私钥将 .pfx 文件转换为密钥库?

    我需要签署 Android 应用程序 apk I have pfx文件 我把它转换为 cer通过 Internet Explorer 文件然后转换 cer to keystore使用密钥工具 然后我尝试签名 apk与 jarsigner 但
  • Spring Boot - 处理 NoHandlerFoundException

    阅读关于如何处理 NoHandlerFoundException 的 Spring 参考指南发现Spring默认设置 throwExceptionIfNoHandlerFound to false 知道了这一点 我认为将此参数设置为一个好主
  • NSWindow 可恢复并不总是有效

    我已经检查了 NSWindow 上的可恢复选项 当我移动应用程序并更改其大小并关闭 重新打开应用程序时 它将窗口大小和位置设置为最后的大小和位置 但这并不是在我测试的每台计算机上都会发生 它只发生在少数计算机上 他们没有关于简历的特殊设置
  • C# - 类的通用 HashCode 实现

    我正在研究如何为一个类构建最好的哈希码 我看到了一些算法 我看到了这个 哈希码实现 似乎 NET类的HashCode方法是类似的 通过反映代码来查看 所以问题是 为什么不创建上面的静态类来自动构建 HashCode 只需传递我们视为 键 的
  • vim 中可以对一组行进行排序吗?

    据我所知 vim 的 sort 方法会对每一行进行排序 我有一些代码以 3 行为一组 我该如何排序 请忽略那些糟糕的代码 它是一个遗留应用程序 我想按大小写 AF 行排序 但忽略 分组 国家 地区并换行 case AF country Af
  • 使用 Dagger 2 在库模块中注入应用程序上下文

    我正在构建一个具有一些功能的应用程序 ContentProvider SyncAdapter 作业服务和相关的持久性逻辑 在这些之上是带有 UI 的活动 我试图将所有上述功能放在一个单独的库模块中 因为理论上它们的逻辑是独立的并且可以由任何
  • MSI 错误 - regsvr32 自定义操作失败

    Brief 我有一个安装包 基于 MSI 它尝试注册一个 dll 文件以用作 Windows 资源管理器栏 Internet Explorer 工具栏 自定义动作定义如下 SystemFolder regsvr32 exe s pathto
  • 将字体嵌入 Apache FOP

    我试图让 Apache FOP 使用 Arial 作为字体 到目前为止 还没有运气 在我的 config xml 中它说
  • 使用 inferred_freq 设置 pandas.tseries.index.DatetimeIndex.freq

    考虑DatetimeIndex tidx tidx pd to datetime 2016 07 29 2016 08 31 2016 09 30 print tidx freq print tidx inferred freq print
  • 使用 Boost.Asio 执行干净关闭的标准方法

    我正在使用 Boost Asio 用 C 编写一个跨平台服务器程序 按照 HTTP 服务器示例这一页 我想在不使用特定于实现的 API 的情况下处理用户终止请求 我最初尝试使用标准 C 信号库 但一直无法找到适合 Asio 的设计模式 这W
  • 如何将Shiny应用程序中的表格和绘图作为参数传递给R Markdown?

    在此 Shiny 应用程序中 用户可以上传 csv 文件 以表格和绘图的形式获取结果 我希望能够将结果下载为 PDF 文档 输入文件 I created the input csv file to be used in the app fr
  • Rcpp::compileAttributes() 错误

    我正在尝试编译我制作的一个小包 该包使用 Rcpp 和 RcppArmadillo 一切都运行良好 直到我将我的 Mac 更新到 Sierra 版本 10 12 5 从 Rstudio 版本 1 0 143 构建包时 我现在收到以下错误消息
  • SignalR 不支持 Windows 集成身份验证

    我有一个 ASP NET MVC 4 应用程序 NET 4 5 SIignalR 可以很好地处理基于表单的身份验证 通过 IIS IIS Express 托管 一旦我将应用程序更改为 Windows 集成身份验证
  • 部署到 Elastic Beanstalk 时运行 Django 迁移

    我在 Elastic Beanstalk 上设置了 Django 应用程序 最近对数据库进行了更改 我希望现在将其应用到实时数据库 我知道我需要将其设置为容器命令 在检查数据库后我可以看到迁移已运行 但我不知道如何对迁移进行更多控制 例如
  • 如何获取当前正在显示的tableView的indexPath.row?

    我有一个包含许多值的 tableView 我想获得第一indexPath row当前正在显示的表的值 我怎样才能做到这一点 我在实现 krishnabhadra 的答案时遇到以下错误 出现错误的行是 self table scrollToR
  • urllib 下载在线目录的内容

    我正在尝试制作一个程序 该程序将打开一个目录 然后使用正则表达式来获取幻灯片的名称 然后在本地创建文件并复制其内容 当我运行它时 它似乎可以工作 但是当我实际尝试打开文件时 他们一直说版本错误 from urllib request imp
  • 将 awk 与列值条件结合使用

    我正在学习 awkAWK 编程语言我对其中一个例子有疑问 如果我想打印 3 如果 2 等于一个值 例如1 我正在使用这个运行良好的命令 awk 2 1 print 3
  • 从 angularjs 中的服务调用控制器函数

    我正在使用 socket io 在我的应用程序中启用聊天 并且我正在使用一项服务SocketService执行所有套接字操作 当消息到来时 我想从服务触发控制器的功能SocketService对 UI 进行一些更改 所以我想知道如何从服务访
  • 如何在 redux 操作(或操作中分配的其他回调)上下文中使用 jest 测试 `image.onload`

    我的问题是我正在尝试对一个函数进行单元测试 但不知道如何测试它的一部分 这是一个 React Redux 操作 执行以下操作 1 使用图像 url 检索 json 数据 2 将图像加载到 Image 实例中并将其大小分派给减速器 当使用 I