我的反应代码如下
handleSubmit(event) {
event.preventDefault();
this.setState({ isDone: true });
...do some operations...
this.getName();
}
上面的handleSubmit
是GetNames
组件的一部分,该组件依次调用下面的另一个函数,再次是同一组件的一部分。
getName() {
var urlendPoint = new URL(propertiesInFile.urltoPing)
var params = {
firstName: this.state.firstName,
lastName: this.state.lastName
}
urlendPoint.search = new URLSearchParams(params)
fetch(urlendPoint).then(response => response.json()).then((data) => {
// ...perform some actions...
})
.catch(error => {
alert("Please check the names and try again");
});
}
我正在为上述功能编写测试用例,但没有获得如何模拟获取数据的方法。以下是我的测试用例
describe('GetNames submit', () => {
let wrapper = shallow(<GetNames />).instance();
let getDetailsSpy;
beforeEach(() => {
getDetailsSpy = jest.spyOn(GetDetails.prototype, 'getDetails');
wrapper = shallow(<GetDetails></GetDetails>);
});
afterEach(() => {
jest.resetAllMocks();
});
it('check submit', () => {
expect(wrapper.find('form')).toHaveLength(1);
const formEventMocked = { preventDefault: jest.fn() };
const state = {
firsName: 'test1',
lastName: 'test2',
isDone: false
};
wrapper.setState(state);
wrapper.find('form').simulate('submit', formEventMocked);
fetch.mockResponse(() => getName().then(res => ({body: res})));
expect(getDetailsSpy).toBeCalledTimes(1);
expect(formEventMocked.preventDefault).toBeCalledTimes(1);
expect(wrapper.state('loading')).toBeTruthy();
});
});
在上面,我模拟了getDetails的响应,但是在fetch调用中测试失败,并显示错误ReferenceError: fetch is not defined
。
如何创建此测试用例,以返回fetch调用结果或调用该方法,并使用模拟对象对所有fetch进行测试?
答案 0 :(得分:0)
您可以使用wrapper.instance().someMethod
测试getName
的{{1}}方法。
我在nodejs环境中使用Component
模块,在浏览器环境中也是如此。您可以手动使用node-fetch
方法模拟jest.mock
或node-fetch
模块。
window.fetch
:
index.tsx
import React, { Component } from 'react';
import fetch from 'node-fetch';
import console = require('console');
export interface ISomeComponentState {
firstName: string;
lastName: string;
isDone: boolean;
[key: string]: any;
}
export class SomeComponent extends Component<any, ISomeComponentState> {
constructor(props) {
super(props);
this.state = {
firstName: '',
lastName: '',
isDone: false
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
public render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<label>
firstName:
<input
type="text"
name="firstName"
placeholder="enter your first name"
value={this.state.firstName}
onChange={this.handleInputChange}
/>
</label>
<label>
lastName:
<input
type="text"
name="lastName"
placeholder="enter your last name"
value={this.state.lastName}
onChange={this.handleInputChange}
/>
</label>
<div>
<input type="submit" value="Submit" />
</div>
</form>
</div>
);
}
private handleInputChange(event: React.ChangeEvent<HTMLInputElement>) {
const target = event.target;
const name = target.name;
const value = target.value;
this.setState({ [name]: value });
}
private handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
this.setState({ isDone: true });
const nameMatch = () => {
return !(this.state.firstName.match('^Cel.*') && this.state.firstName.endsWith('on'));
};
if (nameMatch()) {
alert('Please enter a valid name');
return;
}
if (!this.state.lastName.endsWith('on')) {
alert('check lastname too');
return;
}
this.getFullName();
}
private getFullName() {
// const urlendPoint = new URL('https://github.com/mrdulin');
const params = {
firstName: this.state.firstName,
lastName: this.state.lastName
};
const urlendPoint = `https://github.com/mrdulin?fistName=${params.firstName}&lastName=${params.lastName}`;
// (urlendPoint as any).search = new URLSearchParams(params);
return fetch(urlendPoint)
.then(response => response.json())
.then(data => data)
.catch(error => {
alert('Please check the names and try again');
});
}
}
:
index.spec.tsx
带有覆盖率报告的单元测试结果:
import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import { SomeComponent, ISomeComponentState } from './';
import console = require('console');
import fetch from 'node-fetch';
const { Response } = jest.requireActual('node-fetch');
jest.mock('node-fetch', () => jest.fn());
describe('SomeComponent', () => {
describe('#handleSubmit', () => {
let wrapper: ShallowWrapper;
let getFullNameSpy;
let alertSpy;
beforeEach(() => {
alertSpy = jest.spyOn(window, 'alert');
getFullNameSpy = jest.spyOn(SomeComponent.prototype as any, 'getFullName');
wrapper = shallow(<SomeComponent></SomeComponent>);
});
afterEach(() => {
jest.resetAllMocks();
getFullNameSpy.mockRestore();
});
it('check submit', () => {
expect(wrapper.find('form')).toHaveLength(1);
getFullNameSpy.mockResolvedValueOnce('fullName');
const formEventMocked = { preventDefault: jest.fn() };
const state: ISomeComponentState = {
firstName: 'Cel.du.on',
lastName: 'lin.on',
isDone: false
};
wrapper.setState(state);
expect(wrapper).toMatchSnapshot();
wrapper.find('form').simulate('submit', formEventMocked);
expect(getFullNameSpy).toBeCalledTimes(1);
expect(formEventMocked.preventDefault).toBeCalledTimes(1);
expect(wrapper.state('isDone')).toBeTruthy();
});
it('should alert when first name is invalid', () => {
expect(wrapper.find('form')).toHaveLength(1);
const formEventMocked = { preventDefault: jest.fn() };
const state: ISomeComponentState = {
firstName: 'du',
lastName: 'lin.on',
isDone: false
};
wrapper.setState(state);
expect(wrapper).toMatchSnapshot();
wrapper.find('form').simulate('submit', formEventMocked);
expect(alertSpy).toBeCalledWith('Please enter a valid name');
expect(formEventMocked.preventDefault).toBeCalledTimes(1);
expect(wrapper.state('isDone')).toBeTruthy();
});
it('should alert when last name is invalid', () => {
expect(wrapper.find('form')).toHaveLength(1);
const formEventMocked = { preventDefault: jest.fn() };
const state: ISomeComponentState = {
firstName: 'Cel.du.on',
lastName: 'lin',
isDone: false
};
wrapper.setState(state);
expect(wrapper).toMatchSnapshot();
wrapper.find('form').simulate('submit', formEventMocked);
expect(alertSpy).toBeCalledWith('check lastname too');
expect(formEventMocked.preventDefault).toBeCalledTimes(1);
expect(wrapper.state('isDone')).toBeTruthy();
});
});
describe('#getFullName', () => {
let wrapper: ShallowWrapper;
let alertSpy;
beforeEach(() => {
alertSpy = jest.spyOn(window, 'alert');
wrapper = shallow(<SomeComponent></SomeComponent>);
});
it('should fetch data correctly', async () => {
(fetch as jest.MockedFunction<typeof fetch>).mockResolvedValueOnce(
new Response(JSON.stringify({ data: 'mocked data' }))
);
wrapper.setState({ firstName: 'du', lastName: 'lin' });
const actualValue = await (wrapper.instance() as any).getFullName();
expect(actualValue).toEqual({ data: 'mocked data' });
expect(fetch).toBeCalledWith(`https://github.com/mrdulin?firstName=du&lastName=lin`);
});
it('should alert when fetch data error', async () => {
const mockedFetchError = new Error('some error');
(fetch as jest.MockedFunction<typeof fetch>).mockRejectedValueOnce(mockedFetchError);
wrapper.setState({ firstName: 'lin', lastName: 'du' });
const actualValue = await (wrapper.instance() as any).getFullName();
expect(actualValue).toBeUndefined();
expect(fetch).toBeCalledWith(`https://github.com/mrdulin?firstName=lin&lastName=du`);
expect(alertSpy).toBeCalledWith('Please check the names and try again');
});
});
});
以下是完整的演示:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58085900