无法通过以下测试... 很抱歉放置很多代码。 我还可以使用其他一些点击事件,但此刻我对此仍然感到困惑
获取以下消息:
“ expect(jest.fn())。toHaveBeenCalled()
预计将调用模拟函数。”
这是Render方法下的click事件
className={!this.state.name || !this.state.label || this.state.valueStore === null ? `add-custom-field-button disabled` : `add-custom-field-button`}
id="test-addclick"
onClick={() => {this.onAddClick()}}
>
Create Field
</button>
这是onAddClick方法:
onAddClick = () => {
let obj = this.props.selectedFormJSON;
this.addValueAttribute().then(()=>{
obj.FORM_COLUMN.push(
{
Control: this.state.control,
CreateBy: this.props.user.userId,
Datatype: this.state.datatype,
Form_UID: this.props.selectedFormJSON.Form_UID,
Help: this.state.help,
ValueStore: this.state.valueStore
}
)
this.props.updateSelectedFormJSON(obj);
if(!this.props.isNewForm && this.state.valueStore) {
this.props.patchForm().then((res)=>{
if(res.Forms[0] && (res.Forms[0].Code === '200' || res.Forms[0].Code===200)) {
toast(<div>Attribute Added Successfully!</div>, {type: toast.TYPE.SUCCESS,position: toast.POSITION.TOP_LEFT})
} else {
toast(<div>Failed to Add Attribute!</div>, {type: toast.TYPE.ERROR,position: toast.POSITION.TOP_LEFT})
}
});
} else if(this.state.valueStore) {
this.props.postForm().then((res)=>{
if(res.Forms[0] && (res.Forms[0].Code === '201' || res.Forms[0].Code===201)) {
toast(<div>Attribute Added Successfully!</div>, {type: toast.TYPE.SUCCESS,position: toast.POSITION.TOP_LEFT})
} else {
toast(<div>Failed to Add Attribute!</div>, {type: toast.TYPE.ERROR,position: toast.POSITION.TOP_LEFT})
}
})
}
this.props.closeModal();
})
}
addValueAttribute = () => {
return new Promise((resolve, reject) => {
if(this.state.valueStore) {
let {valueTables, valueDatatypes, service} = this.state;
let body = {
Name: this.state.name,
TableName: this.props.selectedFormJSON.Entity,
Datatype: this.state.datatype,
ChangeType: 'I'
}
fetch(service.URL+'/VALUE_ATTRIBUTE', { headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': service.subscription_key,
},
method: 'POST',
credentials: 'include',
body: JSON.stringify(body),
})
.then((res) => {
res.status === 201 && resolve();
})
.catch(() => {
reject();
})
} else {
//Not a value attr
resolve()
}
})
}
这是我尝试测试的方式:使用笑话/酶。我在其他一些点击事件中使用了相同的设置,但它一直在起作用。无法找出以下原因:
it("should call onAddClick", async () => { // use an async test method
baseProps. closeModal.mockClear();
baseProps. updateSelectedFormJSON.mockClear();
const instance = wrapper.instance();
const spy = jest.spyOn(instance, 'addValueAttribute'); // spy on addValueAttribute...
spy.mockImplementation(() => Promise.resolve()) // give any callbacks queued in PromiseJobs a chance to run
wrapper.find('#test-addclick').at(0).simulate('click'); // simulate click
expect(baseProps.updateSelectedFormJSON).toHaveBeenCalled(); // SUCCESS
expect(baseProps.closeModal).toHaveBeenCalled(); // SUCCESS
});
答案 0 :(得分:0)
addValueAttribute
昂贵,因此您需要模拟它以立即解决。
addValueAttribute
是class field,因此您需要使用组件实例对其进行模拟。
调用onAddClick
时,它将调用this.addValueAttribute
,它将被模拟以立即返回。这将导致Promise
中的then
回调被添加到the PromiseJobs queue中。在当前消息完成之后和下一条消息开始之前,该队列中的作业运行。
这意味着,当点击处理程序返回并继续测试时,在PromiseJobs队列中排队调用this.props.updateSelectedFormJSON
和this.props.closeModal
的回调。
这时,您需要暂停测试以使PromiseJobs中排队的回调有机会运行。最简单的方法是使测试函数async
并调用await Promise.resolve();
,这实际上将把其余测试放在PromiseJobs队列的末尾,并允许队列中已有的任何作业运行首先。
将所有内容放在一起,这是经过测试的代码简化版本:
import * as React from 'react';
import { shallow } from 'enzyme';
class Comp extends React.Component {
onAddClick = () => {
this.addValueAttribute().then(() => {
this.props.updateSelectedFormJSON();
this.props.closeModal();
})
}
addValueAttribute = () => {
return new Promise((resolve) => {
setTimeout(resolve, 100000); // does something computationally expensive
});
}
render() {
return (<button onClick={this.onAddClick}>Create Field</button>);
}
}
it("should call onAddClick", async () => { // use an async test method
const props = {
updateSelectedFormJSON: jest.fn(),
closeModal: jest.fn()
}
const wrapper = shallow(<Comp {...props} />);
const instance = wrapper.instance();
const spy = jest.spyOn(instance, 'addValueAttribute'); // spy on addValueAttribute...
spy.mockResolvedValue(); // ...and mock it to immediately resolve
wrapper
.find('button')
.at(0)
.simulate('click'); // simulate click
await Promise.resolve(); // give any callbacks queued in PromiseJobs a chance to run
expect(props.updateSelectedFormJSON).toHaveBeenCalled(); // SUCCESS
expect(props.closeModal).toHaveBeenCalled(); // SUCCESS
});