runAllTicks()
import React from 'react';
import Promise from 'bluebird';
function doSomethingWithAPromise() {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 50);
});
}
export default class AsyncTest extends React.Component {
constructor(props) {
super(props);
this.state = {
promiseText: '',
timeoutText: ''
};
this.setTextWithPromise = this.setTextWithPromise.bind(this);
this.setTextWithTimeout = this.setTextWithTimeout.bind(this);
}
setTextWithPromise() {
return doSomethingWithAPromise()
.then(() => {
this.setState({ promiseText: 'there is text!' });
});
}
setTextWithTimeout() {
setTimeout(() => {
this.setState({ timeoutText: 'there is text!' });
}, 50);
}
render() {
return (
<div>
<div id="promiseText">{this.state.promiseText}</div>
<button id="promiseBtn" onClick={this.setTextWithPromise}>Promise</button>
<div id="timeoutText">{this.state.timeoutText}</div>
<button id="timeoutBtn" onClick={this.setTextWithTimeout}>Timeout</button>
</div>
);
}
}
任意答案:使用
import AsyncTest from '../async';
import { shallow } from 'enzyme';
import React from 'react';
jest.unmock('../async');
describe('async-test.js', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<AsyncTest />);
});
// FAIL
it('displays the promise text after click of the button', () => {
wrapper.find('#promiseBtn').simulate('click');
jest.runAllTicks();
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('#promiseText').text()).toEqual('there is text!');
});
// PASS
it('displays the timeout text after click of the button', () => {
wrapper.find('#timeoutBtn').simulate('click');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('#timeoutText').text()).toEqual('there is text!');
});
});
async
导致更清洁的代码。下面的旧代码
我通过组合以下元素成功解决了这个问题:毫无根据并立即解决诺言 通过标记测试函数来制定测试异步
在模拟点击之后,请等到下一个macrotask
给出了承诺的时间解决在您的例子中,可能看起来像这样:
await
相同的逻辑,但略微漂亮。使用Node的
async
// Mock the promise we're testing
global.doSomethingWithAPromise = () => Promise.resolve();
// Note that our test is an async function
it('displays the promise text after click of the button', async () => {
wrapper.find('#promiseBtn').simulate('click');
await tick();
expect(wrapper.find('#promiseText').text()).toEqual('there is text!');
});
// Helper function returns a promise that resolves after all other promise mocks,
// even if they are chained like Promise.resolve().then(...)
// Technically: this is designed to resolve on the next macrotask
function tick() {
return new Promise(resolve => {
setTimeout(resolve, 0);
})
}
以异步完成测试。
update()
这不太好,因为如果您必须等待多个诺言,您会得到大嵌套回调。
在结束测试之前,并不需要以某种方式等待承诺实现的承诺。从您的代码中,我可以看到两种主要方法。独立于测试setImmediate
和您的承诺方法。因此,请检查是否调用正确的功能,但请在done
上间谍,触发单击并断言
global.doSomethingWithAPromise = () => Promise.resolve({});
it('displays the promise text after click of the button', (done) => {
wrapper.find('#promiseBtn').simulate('click');
setImmediate( () => {
expect(wrapper.find('#promiseText').text()).toEqual('there is text!');
done();
})
});
被调用。然后,您还可以获取组件实例并调用该方法,该方法返回承诺您可以附加处理程序并断言它做对的事情。
在承诺解决时,可以曝光一个可以通过的回调道具。
如果您使用开玩笑,也可以使用
onClick
和
onClick
setTextWithPromise