Cod*_*Lee 1 javascript reactjs jestjs window.crypto
当使用Jest进行运行单元测试时,window.crypto API会引起问题。我还没有找到一种在不安装其他软件包的情况下将加密合并到Jest中的方法,这是我做不到的。因此,无需使用其他npm软件包,就可以测试使用的功能:crypto.getRandomValues()在其中不会崩溃的Jest?任何链接,建议或技巧,不胜感激
Mic*_*ael 22
对于nodeJS + typescript,只需使用global而不是global.self
import crypto from 'crypto'
Object.defineProperty(global, 'crypto', {
value: {
getRandomValues: (arr:any) => crypto.randomBytes(arr.length)
}
});
Run Code Online (Sandbox Code Playgroud)
小智 9
像@RwwL 一样,接受的答案对我不起作用。我发现这个库中使用的 polyfill 确实有效:commit with polyfill
//setupTests.tsx
const nodeCrypto = require('crypto');
window.crypto = {
getRandomValues: function (buffer) {
return nodeCrypto.randomFillSync(buffer);
}
};
Run Code Online (Sandbox Code Playgroud)
//jest.config.js
module.exports = {
//...
setupFilesAfterEnv: ["<rootDir>/src/setupTests.tsx"],
};
Run Code Online (Sandbox Code Playgroud)
当前答案中的填充是不完整的,因为Crypto.getRandomValues()就地修改了它的参数并返回它。const foo = new Int8Array(8); console.log(foo === crypto.getRandomValues(foo))您可以通过在浏览器控制台中运行类似的命令来验证这一点,该控制台将打印true.
getRandomValues()也不接受 anArray作为其参数,它只接受整数TypedArrays。Node.js 的crypto.randomBytes()函数不适合这个 polyfill,因为它输出原始字节,而getRandomValues()可以接受元素最多为 32 位的有符号整数数组。如果您crypto.getRandomValues(new Int32Array(8))在浏览器中尝试,您可能会看到类似的内容[ 304988465, -2059294531, 229644318, 2114525000, -1735257198, -1757724709, -52939542, 486981698 ]。但如果您尝试node -e 'console.log([...require("crypto").randomBytes(8)])'使用命令行,您可能会看到[ 155, 124, 189, 86, 25, 44, 167, 159 ]. 显然,这些并不等效,并且如果使用后者进行测试,您的被测组件可能不会按预期运行。
最新版本的 Node.js 通过webcrypto模块解决了这个问题(应该是设置问题globalThis.crypto = require('crypto').webcrypto)。如果您使用旧版本的 Node(v14 或更低版本),您可能会更好地使用crypto.randomFillSync(),它应该可以用作 的直接替代品,因为它会就地getRandomValues()修改传递的缓冲区/ 。TypedArray
在 Jest 设置文件中(无法通过globals配置进行设置,因为它只允许 JSON 兼容的值):
const { randomFillSync } = require('crypto')
Object.defineProperty(globalThis, 'crypto', {
value: { getRandomValues: randomFillSync },
})
Run Code Online (Sandbox Code Playgroud)
jsdom对于使用( jest-environment-jsdom) 环境的用户,Jest >=28您应该将替换模块定义为getter。
//jest.config.js
module.exports = {
testEnvironment: "jsdom",
rootDir: './',
moduleFileExtensions: ['ts', 'js'],
setupFilesAfterEnv: ["<rootDir>/test/setup-env.tsx"],
preset: 'ts-jest',
};
Run Code Online (Sandbox Code Playgroud)
// setup-env.tsx
const { Crypto } = require("@peculiar/webcrypto");
const cryptoModule = new Crypto();
Object.defineProperty(window, 'crypto', {
get(){
return cryptoModule
}
})
Run Code Online (Sandbox Code Playgroud)
我正在使用@peculiar/webcrypto,但其他实现也应该可以工作。
我正在使用 vue-jest,对我有用的是文件中的以下配置jest.config.js:
module.exports = {
...
setupFiles: [
'<rootDir>/tests/settings/jest.crypto-setup.js',
],
};
Run Code Online (Sandbox Code Playgroud)
并在jest.crypto-setup.js:
global.crypto = {
getRandomValues: (arr) => require('crypto').randomBytes(arr.length)
};
Run Code Online (Sandbox Code Playgroud)
getRandomValues直接添加函数定义module.exports不起作用,因为globals对象必须是 json 可序列化的(如此处指定的: https: //jestjs.io/docs/configuration#globals-object)。
来自 AIVeligs 的答案:
由于我在 Jest 中使用“节点”环境,所以我必须使用
module.exports = {
preset: "ts-jest",
testEnvironment: "node",
globals: {
crypto: {
getRandomValues: (arr) => require("crypto").randomBytes(arr.length),
},
},
};
Run Code Online (Sandbox Code Playgroud)
这应该做。使用以下代码crypto全局设置属性。这将允许Jest访问,window.crypto并且不会引起任何问题。
const crypto = require('crypto');
Object.defineProperty(global.self, 'crypto', {
value: {
getRandomValues: arr => crypto.randomBytes(arr.length),
},
});
Run Code Online (Sandbox Code Playgroud)
从节点 15.x 开始,您可以使用 crypto.webcrypto
例如。
import crypto from "crypto";
Object.defineProperty(global.self, "crypto", {
value: {
subtle: crypto.webcrypto.subtle,
},
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1161 次 |
| 最近记录: |