为什么如果从另一个模块调用该模块,则改变模块会更新引用,但如果从自身调用则不会?

2023-11-30

这个问题涉及测试 javascript 和模拟函数。

假设我有一个如下所示的模块:

export function alpha(n) {
    return `${n}${beta(n)}${n}`;
}

export function beta(n) {
    return new Array(n).fill(0).map(() => ".").join("");
}

那么我无法通过以下方式测试它:

import * as indexModule from "./index";

//Not what we want to do, because we want to mock the functionality of beta
describe("alpha, large test", () => {
    it("alpha(1) returns '1.1'", () => {
        expect(indexModule.alpha(1)).toEqual("1.1"); //PASS
    });

    it("alpha(3) returns '3...3'", () => {
        expect(indexModule.alpha(3)).toEqual("3...3"); //PASS
    });
});

//Simple atomic test
describe("beta", () => {
    it("beta(3) returns '...'", () => {
        expect(indexModule.beta(3)).toEqual("..."); //FAIL: received: 'x'
    });
});

//Here we are trying to mutate the beta function to mock its functionality
describe("alpha", () => {

    indexModule.beta = (n) => "x";
    it("works", () => {
        expect(indexModule.alpha(3)).toEqual("3x3"); //FAIL, recieved: '3...3'
    });
});

但是,如果将模块分成两个:

alpha.js

import { beta } from "./beta";

export function alpha(n) {
    return `${n}${beta(n)}${n}`;
}

beta.js

export function beta(n) {
    return new Array(n).fill(0).map(() => ".").join("");
}

然后我可以改变 beta 模块,并且 alpha 知道它:

import { alpha } from "./alpha";
import * as betaModule from "./beta";

describe("alpha", () => {
    betaModule.beta = (n) => "x";
    it("works", () => {
        expect(alpha(3)).toEqual("3x3");   //PASS
    });
});

为什么会这样呢?我正在寻找技术上具体的答案。

我有一个包含此代码的 Github 分支here,参见mutateModule and singleFunctionPerModuleAndMutate文件夹。

作为一个附加问题 - 在此示例中,我通过直接重新分配属性来改变模块。我是否正确理解使用笑话模拟功能本质上会做同样的事情?

IE。如果第一个示例不起作用而第二个示例不起作用的原因是由于突变,那么它必然意味着使用 jest 模块模拟函数同样不起作用。

据我所知 - 在测试该模块时没有办法模拟模块中的单个函数,正如这个笑话 github issues 所谈论的。我想知道的是为什么会这样。


为什么如果从另一个模块调用该模块,则改变模块会更新引用,但如果从自身调用则不会?

“在 ES6 中,导入是导出值的实时只读视图”.

当您导入 ES6 模块时,您实际上可以实时查看该模块导出的内容。

实时视图可以发生变化,任何导入模块导出的实时视图的代码都会看到变化。

这就是为什么你的测试在以下情况下有效alpha and beta位于两个不同的模块中。测试修改了实时视图beta模块,并且自从alpha模块使用实时视图beta模块,它会自动使用模拟函数而不是原始函数。

另一方面,在上面的代码中alpha and beta位于同一模块中并且alpha calls beta直接地. alpha does not使用模块的实时视图,因此当测试修改模块的实时视图时,它没有任何效果。


作为一个附加问题 - 在此示例中,我通过直接重新分配属性来改变模块。我是否正确理解使用笑话模拟功能本质上会做同样的事情?

有几种方法可以使用Jest.

其中一种方法是使用jest.spyOn它接受一个对象和一个方法名用调用原始方法的间谍替换对象上的方法.

常见的使用方法jest.spyOn是将 ES6 模块的实时视图作为对象传递给它,该对象会改变模块的实时视图。

所以是的,通过将 ES6 模块的实时视图传递给类似的东西来进行模拟jest.spyOn (or spyOn from Jasmine, or sinon.spy from Sinon等)改变模块的实时视图的方式与直接改变模块的实时视图的方式基本相同,就像您在上面的代码中所做的那样。


据我所知 - 在测试该模块时,没有办法模拟模块中的单个函数,正如这个笑话 github issues 所讨论的那样。我想知道的是为什么会这样。

其实,它is可能的。

“ES6 模块自动支持循环依赖”意思就是模块的实时视图可以导入到模块本身.

只要alpha calls beta使用模块的实时视图beta定义于,则beta测试过程中可以被嘲笑。即使它们是在同一模块中定义的,这也有效:

import * as indexModule from './index'  // import the live view of the module

export function alpha(n) {
    return `${n}${indexModule.beta(n)}${n}`;  // call beta using the live view of the module
}

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

为什么如果从另一个模块调用该模块,则改变模块会更新引用,但如果从自身调用则不会? 的相关文章

  • Angular UI 模式的范围问题

    我无法理解 使用角度 UI 模式的范围 虽然这里不是很明显 但我已经正确设置了模块和所有内容 据我所知 但这些代码示例尤其是我发现错误的地方 index html 其中重要部分 div class btn group div
  • 将 Javascript 对象的属性从 string 更改为 int

    我有一个对象数组 每个对象具有三个属性 年份 总计 人均 例子 0 Object per capita 125 8 total 1007 2 year 2009 这些属性是字符串 我想创建一个循环来遍历数组并将它们转换为 int 我尝试了以
  • 在 HTML5 Javascript 中将 BlobBuilder 转换为字符串

    function blobToString blob var reader new FileReader var d reader onloadend function d callback reader result console lo
  • Jquery 悬停卡

    我在用着http designwithpc com Plugins Hovercard http designwithpc com Plugins Hovercard 但我不知道如何在悬停卡上声明 var 每个工作描述都有自己的 ID 当悬
  • 如何阻止直接访问我的 JavaScript 文件?

    我使用 Minify 来缩小并缓存所有脚本请求 我只希望我的用户能够访问 JavaScript 文件的缩小版本 缩小位于www example com min我的脚本位于www example com scripts 如何阻止直接访问doc
  • 浏览器视口大小(以设备像素为单位)

    Goal 我希望 Flash 能够获得有关浏览器视口宽度和高度 以设备像素为单位 的准确信息初始化 调整大小或浏览器缩放事件时 规格 我需要将 flash 嵌入到在 chrome safari firefox 等中运行的 html 页面中
  • 在特定页面上执行 javascript 的正确“Rails”方式

    我试图在特定页面上运行 javascript 而我唯一的解决方案似乎是反模式 我有controller js内部生成的assets javascripts 我在用着gem jquery turbolinks 我的代码类似于以下内容 docu
  • 如何在没有 jQuery 的情况下删除 Javascript 中的元素

    我试图通过以下方式从 DOM 中删除 Div a 标签嵌套在其中 我想我正在寻找的是 jQuery 的纯 Javascript 版本 div remove 这是html设置 div a href Click me to remove the
  • 使用 Angular 指令禁用文本选择

    我正在学习 JavaScript 和 AngularJS 我想使用 Angular Directive 禁用文本选择 我有该函数的 JavaScript 代码 function clearSelection if document sele
  • IntersectionObserver是否支持水平滚动观察?

    我制作了几个垂直滚动 IntersectionObserver 模块 但我对水平滚动感兴趣 根将是 div 观察目标将是 img 我想观察当 img 放大但 div 保持视口宽度时的变化 我什至不确定移动 Safari 是否会将缩放后的图片
  • JavaScript 验证和 PHP 验证?

    我正在使用 jquery 验证插件来验证空表单 我还应该在 PHP 中检查一下以确保 100 正确吗 或者用 javascript 验证就可以了 谢谢 您应该始终在服务器上进行验证 如果用户以某种方式不使用 Javascript 提交表单
  • javascript 选择自定义光标 (svg)

    我正在动态地将光标更改为悬停时的本地 svg element on mouseover function this css cursor url svgs pointer svg 9 30 auto 工作正常 但我想选择该 svg 来操纵其
  • JavaScript推送函数中的动态变量

    我在 JavaScript 中使用推送功能 var chartData for var i 0 i lt 3 i chartData push date new Date year s mon s date s hr s min s sec
  • 改变 JavaScript 中的顶部填充

    以下是我在 css 中设置顶部填充的方法 body font size font size px margin 0 padding 100px 0 20px 0 width 100 important 如何使用最简单的 javascript
  • 使用 Google 日历源时如何禁用 FullCalendar 中的活动链接?

    我正在使用 FullCalendar 库从 Google 日历加载日历中的事件 不幸的是 事件添加到日历后 它们是可点击的 当您点击该活动时 您会自动重定向到 Google 日历页面以查看该特定活动 或者如果您有足够的访问权限 则可以直接对
  • JavaScript eval("{}") 返回行为?

    根据ECMA 262 规范 http www ecma international org publications files ECMA ST Ecma 262 pdf 以下语句返回1 eval 1 eval 1 eval 1 var a
  • $resource.query 返回分割字符串(字符数组)而不是字符串

    我正在使用像下面这样的 Angular resource angular module app factory data function resource var Con resource api data update method P
  • 使用 next.js 进行服务器端渲染与传统 SSR

    我非常习惯 SSR 意味着页面得到完全刷新并从服务器接收完整 HTML 的方法 其中根据后端堆栈使用 razor pub other 进行渲染 因此 每次用户单击导航链接时 它只会向服务器发送请求 整个页面将刷新 接收新的 HTML 这就是
  • react-native - 图像需要来自 JSON 的本地路径

    你好社区 我正在react native中开发一个测试应用程序 并尝试从本地存储位置获取图像 我实际在做什么 我将图像直接链接源提供给 var 并在渲染函数中调用此方法 react 0 14 8 react native 0 23 1 np
  • 将数组从 jquery ajax 传递到代码后面

    我必须将二维数组传递给在asp net网页代码后面编写的页面方法我有一个变量objList作为二维数组 我使用以下代码来实现此目的 但没有成功 并且未调用页面方法 脚本语言 function BindTable objList ajax u

随机推荐

  • .Net 控制计算机之间大小的变化

    我有一个奇怪的问题 我需要弄清楚如何解决 过去几周我一直在我的笔记本电脑上开发一个项目 但是当我在其中一台工作电脑上打开程序时 很多控件的尺寸错误和重叠等 机器之间的差异是这样的 Laptop Windows 7 专业版 显示 1920 1
  • 在MySQL中,我们如何判断表的索引是否是聚集索引?

    在MySQL中 我们如何判断表的索引是否是聚集索引 我们可以用show index from table name获取有关表索引的信息 但我没有发现它显示每个索引是聚集的还是非聚集的 这样做的目的是MySQL中如果一个表有索引 那么该表就必
  • Django FormWizard 动态改变 form_list

    我在使用表单向导时遇到了一些问题 也许有人可以解释一下 根据 process step 方法中的文档字符串 我可以 动态更改 self form list 因此 根据我的项目需求 我将表单附加到 form list 中 我附加的表格包含问题
  • 在外发电子邮件 EWS 中设置回复地址

    运行交换 2013 我在 C 服务中使用 EWS 该服务从服务帐户发送电子邮件 我想让电子邮件有一个与发送帐户不同的回复地址 即通讯组列表地址 我怎样才能做到这一点 这EmailMessage ReplyTo字段是只读的 Code Exch
  • Django 快捷方式嵌套外键

    假设我的 models py 中有以下内容 class Book pass class Part book models ForeignKey Book class Chapter part models ForeignKey Part n
  • 它不会创建 Java VM (JNI)

    我的简单命令行应用程序 int tmain int argc TCHAR argv JavaVM jvm JNIEnv env JavaVMInitArgs vm args JavaVMOption options 1 options 0
  • 扩展server_name(SNI扩展)不与jdk1.8.0一起发送,但与jdk1.7.0一起发送

    我已经使用 ApacheCXF v3 0 4 实现了 JAX WS 客户端 一切正常 但当我想使用 java 8 jdk1 8 0 25 的安全连接 SSL TLS 时 问题就出现了 我在日志中看到以下异常 Djavax net debug
  • 如何在未知输入类型下使用 cin?

    我有一个 C 程序 需要接受用户输入 用户输入要么是两个整数 例如 1 3 要么是一个字符 例如 s 我知道我可以像这样得到两个整数 cin gt gt x gt gt y 但是 如果输入的是 char 我该如何获取 cin 的值呢 我知道
  • 在 IIS Express 中配置最大请求数

    如何配置 IIS Express 中允许的最大请求数 我想将其更改为仅允许一些请求来测试超出限制时会发生什么 可以使用以下方式配置 IIS ExpressapplicationHost config文件 它位于 userprofile my
  • Java - 如何将 PDF 打印到特定打印机?

    我在 Windows 8 1 中有 5 台打印机 并且 PDF 文件不在本地系统中 而是在 PHP 服务器中生成的 问题 如何从服务器获取 PDF 文件并打印到特定打印机 我正在尝试使用 Apache PDFBox 2 0 0 EDIT i
  • 如何分解行? [复制]

    这个问题在这里已经有答案了 我有一个数据表 如下所示 cep3 lt structure list lat c 23 39429 23 39988 23 38233 23 39009 23 40135 23 4019 lon c 46 32
  • 替换 tel 或 telprompt 拨打电话

    我制作了一个应用程序 用于在按下按钮时呼叫预定义的号码 据我所知 在应用程序内拨打电话的唯一方法是使用 tel 或 telprompt 当我提交应用程序时 我收到了带有以下描述的拒绝 2 5 详情 您的应用程序使用或引用以下非公共 API
  • php中事件的含义

    我也知道php和nodejs 在javascript中我们有异步编程 所以我理解其中事件的含义 但是我看到了Yii 和 Zend 2 中的事件也使用它们 但我无法理解它的含义 它在 php 中如何工作以及它到底有什么作用 首先 PHP中没有
  • 如何读取Android设备上的CPU频率[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 有没有 Java API 可以实现这一点 我怎样才能阅读这些信息 要在 Android 上获得频率 只需读取 sys 目录中的这些特殊文件 cat
  • 根据另一个日期选择器实例更改 jQuery 日期选择器中显示的月份

    我有两个日期选择器字段 一个是 开始日期 另一个是 end date 我想要一个功能 在用户选择 开始日期 然后是 end date 日历应默认显示包含 开始日期 反之亦然 如果用户首先选择end date 日历为开始日期应显示包含所选的月
  • Spring Boot 2.7.1 与 JSF 2.2 (Mojarra) 和 Primefaces 6.2.9 集成

    我已经使用下面的堆栈进行了工作设置 春季MVC 5JSF Mojarra 2 2 14Primefaces 6 2 9 该应用程序是作为 WAR 构建的 它具有配置了 FacesServlet 的 web xml 来服务 xhtml 请求
  • 转换字符(强制转换与 .getNumericValue)

    为什么casting int 可以正确地将符号的char转换为int 但是 Character getNumericValue someSymbolCharValue 不能 E g Character getNumericValue 即使
  • 使用 Jackson 进行自定义反序列化:扩展默认反序列化器

    我想通过扩展默认解串器并在其后设置更多值来制作自己的解串器 simplified code public class Dto public String originalJsonString public MyFooDto extends
  • Symfony 2,Twig:如何不转义字段值(与backbonejs和symfony 2一起使用)

    我正在使用以下代码渲染原型 form widget form get prototype myField attr value 骨干JS应该读取此树枝块生成的代码 并将 替换为某个模型属性值 这种情况不会发生 因为该值在 twig 中被转义
  • 为什么如果从另一个模块调用该模块,则改变模块会更新引用,但如果从自身调用则不会?

    这个问题涉及测试 javascript 和模拟函数 假设我有一个如下所示的模块 export function alpha n return n beta n n export function beta n return new Arra