我好像搞不明白这件事。我使用创建-反应-应用程序,它是内置于测试运行Jest。对于所有同步代码来说,它似乎运行得很好,但是当嘲笑承诺时,我似乎无法让它工作起来。
react组件有一个表单,我可以模拟提交。
响应组件代码段。
//Top of the page
import {auth} from '../../lib/API_V2'
// ... //
// Handle submit runs when the form is submitted
handleSubmit = (event) => {
console.log('submit')
event.preventDefault()
this.setState(prevState => ({
...prevState,
loading: true
}))
console.log('stateSet')
auth(this.state.userName, this.state.password)
.then(results => {
// NEVER RUNS
console.log('then')
// stuff omitted
this.setState(prevState => ({
...prevState,
loading: false
}))
this.props.afterAuth()
})
.catch(() => {
// also never runs
// omitted
this.setState(prevState => ({
...prevState,
loading: false
}))
this.props.afterAuth()
})
}测试代码
jest.mock('../../lib/API_V2')
it.only(`should mock a login`, () => {
const myMock = jest.fn()
const authComp = mount(<AuthComponent afterAuth={myMock}/>)
authComp.find('.userName').simulate('change', {target: {value: 'userName'}})
authComp.find('.password').simulate('change', {target: {value: 'password'}})
expect(authComp.state().userName).toEqual('userName')
expect(authComp.state().password).toEqual('password')
authComp.find('[type="submit"]').get(0).click()
expect(myMock.mock.calls.length).toBe(1) // FAILS
})API库返回一个承诺。我没有使用它,而是在它旁边有一个__mocks__/API_V2.js。看上去像这样
function auth (lastname, accountNumber) {
console.log('yay!?')
return new Promise((resolve) => {
resolve({
accountNumber,
lastName: lastname
})
})
} 我的模拟测试代码似乎从未运行过。如果我记录了模拟函数,就会得到function auth() {return mockConstructor.apply(this,arguments);}
我尝试遵循https://facebook.github.io/jest/docs/tutorial-async.html的指令,但似乎没有调用我的模拟方法。而实际的方法也是如此。相反,我对auth()的调用返回未定义的。
有人有什么想法吗?
-补充资料--
src
Components
AuthComponent
AuthComponent.js
AuthComponent.test.js
index.js
Lib
API_V2
API_V2.js
index.js
__mocks__
API_V2.js发布于 2017-02-16 00:17:18
我认为你碰到了一个与这个问题相关的bug:https://github.com/facebook/jest/issues/2070
由于您实际上试图导入一个名为API_V2/index.js的文件,所以需要模拟index.js。但是,这样做将非常困难,因为它将是您试图模拟的每个index.js文件的有效模拟。
目前最好的方法是重写一些代码,以使用依赖注入,并将模拟传递给任何需要使用{ auth }的代码。
发布于 2017-02-16 02:07:09
在模拟的新承诺中,即使您立即解决,此解析也不会同步发生。承诺回调总是作为一个排队的微任务运行,所以当您在测试中模拟单击时,模拟中的承诺回调还没有运行(因此myMock也还没有被调用)。这就是你的期望失败的原因。
解决这个问题的一种(有点麻烦的)方法是使用setTimeout。setTimeout将为任务排队,任务总是在微任务之后运行。Jest通过从it回调返回承诺来支持异步测试,因此您可以编写:
jest.mock('../../lib/API_V2')
it.only(`should mock a login`, () => new Promise(resolve => {
const myMock = jest.fn()
const authComp = mount(<AuthComponent afterAuth={myMock}/>)
authComp.find('.userName').simulate('change', {target: {value: 'userName'}})
authComp.find('.password').simulate('change', {target: {value: 'password'}})
expect(authComp.state().userName).toEqual('userName')
expect(authComp.state().password).toEqual('password')
authComp.find('[type="submit"]').get(0).click()
setTimeout(() => {
expect(myMock.mock.calls.length).toBe(1)
resolve() // Tell jest this test is done running
}, 0);
}))这里很好地解释了任务和微任务是如何工作的:https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
https://stackoverflow.com/questions/42259825
复制相似问题