0

0

笑话回顾:安全模拟全局对象的属性和方法

PHPz

PHPz

发布时间:2024-07-18 21:01:07

|

890人浏览过

|

来源于dev.to

转载

笑话回顾:安全模拟全局对象的属性和方法

长话短说:

  • 您希望避免覆盖/模拟的属性/方法影响其他测试。
  • 对于本地对象(由该测试创建并拥有),您可以(并且应该)使用
    • localobject.theanswer = 42 和
    • localobject.calctheanswer = jest.fn(() => 42).
  • 对于全局对象,您应该使用
    • jest.replaceproperty(globalobject, "theanswer", 42) 和
    • jest.spyon(globalobject, "calctheanswer").mockreturnvalue(42).
  • 确保在 aftereach() 钩子中调用 jest.restoreallmocks() 。

什么?

在完美的世界代码库中,不需要操作全局对象,但是世界代码库很混乱 - 测试也是如此。

您要不惜一切代价避免一个测试影响另一个测试。无论顺序如何,或者是否跳过某些测试,测试都应该有意义。

模拟属性

模拟值的一种简单方法是将属性设置为测试中所需的任何值。
只要您更改此特定测试拥有(创建)的本地对象中的值就可以了:

describe("override properties of local objects", () => {
    it("works and is harmless", () => {
        const myarray = [1];
        myarray.length = 0;
        expect(myarray).tohavelength(0);
    });
    it("does not affect the next test", () => {
        const myarray = [1];
        expect(myarray).tohavelength(1);
    });
});

如果你对全局对象这样做,它会变得混乱:

describe("don't override properties of global objects", () => {
    it("works before the property is overridden", () => {
        expect(window.innerwidth).tobegreaterthan(0);
    });
    it("works, but is evil", () => {
        window.innerwidth = 0;
        expect(window.innerwidth).tobe(0);
    });
    it("fails in the test after the property was overridden", () => {
        expect(() => {
            expect(window.innerwidth).tobegreaterthan(0); // <-- error: expect(received).tobegreaterthan(expected)
        }).tothrow(error);
    });
});

这就是 jest.replaceproperty() 的用途:

describe("use jest.replaceproperty() to override properties of global objects", () => {
    aftereach(() => {
        jest.restoreallmocks();
    });
    it("works before the property is overridden", () => {
        expect(window.innerwidth).tobegreaterthan(0);
    });
    it("works and is harmless", () => {
        jest.replaceproperty(window, "innerwidth", 0);
        expect(window.innerwidth).tobe(0);
    });
    it("does not affect the next test", () => {
        expect(window.innerwidth).tobegreaterthan(0);
    });
});

模拟方法

方法可以像属性一样被模拟。

describe("override methods of local objects using jest.fn()", () => {
    it("works and is harmless", () => {
        const myset = new set([1]);
        myset.has = jest.fn().mockreturnvalue(false);
        expect(myset.has(1)).tobefalsy();
    });
    it("does not affect the next test", () => {
        const myset = new set([1]);
        expect(myset.has(1)).tobetruthy();
    });
});

如果你在全局对象上使用 myobject.somefunction = jest.fn() ,你的测试可能会相互依赖并失去它们的意义:

describe("don't override methods of global objects using jest.fn()", () => {
    it("works before the method is overridden", () => {
        expect(document.getelementbyid("foo")).tobenull();
    });
    it("works, but is evil", () => {
        const el = document.createelement("div");
        document.getelementbyid = jest.fn().mockreturnvalue(el);

        expect(document.getelementbyid("foo")).tobe(el);
    });
    it("fails in the test after the property was overridden", () => {
        expect(() => {
            expect(document.getelementbyid("foo")).tobenull(); // <-- error: expect(received).tobenull()
        }).tothrow(error);
    });
});

我们应该如何模拟全局对象中的方法?这就是 jest.spyon() 的好处:

考拉新媒体导航
考拉新媒体导航

考拉新媒体导航——新媒体人的专属门户网站

下载
describe("use jest.spyOn() to override methods of global objects", () => {
    afterEach(() => {
        jest.restoreAllMocks();
    });
    it("works before the method is overridden", () => {
        expect(document.getElementById("foo")).toBeNull();
    });
    it("works and is harmless", () => {
        const el = document.createElement("div");
        jest.spyOn(document, "getElementById").mockReturnValue(el);

        expect(document.getElementById("foo")).toBe(el);
    });
    it("does not affect the next test", () => {
        expect(document.getElementById("foo")).toBeNull();
    });
});

你必须清理

如果你想确保所有测试都发现系统处于相同(新鲜、干净)状态,则需要在每次测试后恢复模拟的状态。

最简单的解决方案是设置restoremocks配置属性。

最直接的选择是在 aftereach() 中调用 jest.restoreallmocks()

如何为所有测试模拟某些内容

有时您想模拟文件中所有测试的内容。如果您在顶层或在describe()块中使用jest.spyon()和jest.replaceproperty(),则在执行第一个测试后,所有mock将被重置。

在顶层,您可以安全地重写属性和方法,无需 jest.spyon() 和 jest.replaceproperty()。

如果您只想为describe() 块模拟事物,则需要在beforeeach() 挂钩中进行这些调用。

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

1

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

2

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

0

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

0

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

3

2026.01.29

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

24

2026.01.29

clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址
clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址

clawdbot龙虾机器人官网入口:https://clawd.bot/,clawdbot ai是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

16

2026.01.29

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

8

2026.01.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

577

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号