javascript - 来自 Jest mockImplementation 的意外行为
问题描述
我有代码要编写测试以供以后重构,因此我无法更改代码或任何依赖项。这是问题所在:
// foo.js
Knex = require('knex')
module.exports ={func}
// calling this inside func will
// have the expected {a:4}
client = Knex()
async function func(){
console.log(client)
return true
}
// foo.spec.js
const foo = require('./foo')
const Knex = require('knex')
jest.mock('knex', ()=>jest.fn())
describe('jest.mockImplementation',()=>{
it('should mock knex',async ()=>{
Knex.mockImplementation(()=>({a:4}))
// alternative, I can put
// const foo = require('./foo')
// here
await foo.func()
})
})
// jest.config.js
module.exports={
"verbose": true,
"testEnvironment": "node",
}
//package.json
{
"dependencies": {
"jest": "^26.6.3",
"knex": "0.19.3"
}
}
我运行:
$ jest --config jest.config.js --runInBand foo.spec.js
并且我希望有一个控制台日志{ a : 4}
,但它是undefined
. 但是请注意,如果我移动client
内部,func
那么它将记录{a : 4}
或者,如果我离开client
它所在require
foo
的位置和spec.js
之后mockImplementation
,它将再次具有预期的控制台日志。
我本来希望看到client
在外部创建的正确行为func
,而不需要require
foo
after mockImplementation
。
为什么会发生这种情况,我怎样才能在不移动的情况下获得所需的行为client
?require
函数里面也ing 不是最好的。
我创建了这个 repl.it 进行实验;请不要更新它以供他人使用:
解决方案
模块作用域的代码会在需要模块时立即执行,所以在测试用例中提供模拟实现已经来不及了。
jest.mock()
将被提升到测试文件的顶部。它将在require
语句之前执行,因此当需要模块时,jest.mock()
将使用中提供的模拟实现。
在内部提供一个模拟实现,jest.mock()
如下所示:
const foo = require('./foo');
jest.mock('knex', () => jest.fn(() => ({ a: 4 })));
describe('jest.mockImplementation', () => {
it('should mock knex', async () => {
await foo.func();
});
});
测试结果:
PASS examples/66881537/foo.spec.js (6.347 s)
jest.mockImplementation
✓ should mock knex (15 ms)
console.log
{ a: 4 }
at Object.<anonymous> (examples/66881537/foo.js:8:11)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 6.789 s
推荐阅读
- java - 有什么方法可以在java中读取导入项目的文件路径?
- python - Scipy fsolve 不接受虚构值
- python - 仅当它们在python的列表中出现多次时如何打印值
- python - 如何指定特定的 conda 环境来运行 pytest 代码?
- php - Symfony 4 的 Rest-bundle 需要 4.3 版本的配置,而 Symfony 4 使用 5.0
- c# - PostgreSql:我们如何在 C# 中调用存储过程 inout 参数?
- node.js - openvidu 视频组会议收到请求的令牌错误错误
- ios - Xcode 11.2.1 重新缩进破坏了标记语法格式
- python - Dockerfile 中的 pip install 失败
- java - 重命名所有 JSON 键 - Java - Jackson - springboot