我为React组件创建了一个单元测试。如果没有提供电子邮件地址,则第一个测试应该通过,并且我们提醒用户没有提供。这作为单独的测试以及整个套件运行都通过。如果提供了电子邮件但没有提供密码,则第二项测试应该通过,并通过一条消息提示用户需要提供密码来提醒用户。
我看到的问题是,如果我告诉密码单元测试来检查警报是否未提供电子邮件。在这种情况下,如果我单独运行测试,它将失败,表示需要按预期提供电子邮件。但是,如果我将它作为套件运行,并且首先运行了电子邮件检查,则密码检查单独运行了,如果不应该提供密码,则密码检查通过,因为提供了电子邮件地址并且警报消息应该没有密码。如果我先使用密码检查来运行测试套件,然后将电子邮件检查与电子邮件检查分开,则密码检查会按我的预期失败。根据测试的执行顺序,我会得到不同的结果。
我已经尝试通过命令行运行选项--env = jsdom --watchAll = false --coverage,使用package.json中的npm配置,并使用webstorm运行配置,但是它们都产生相同的结果结果。
单元测试:
import React from 'react';
import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16.3';
import SignInForm from '../components/SignInForm';
//import { mount, shallow, render } from 'enzyme';
configure({ adapter: new Adapter() });
test('Errors when no email is input', () => {
jest.spyOn(window, 'alert').mockImplementation(() => {});
const wrapper = shallow(<SignInForm />);
wrapper.find('input#email_address').simulate('change', {target: { value: '' }});
wrapper.find('button').simulate('click');
expect(window.alert).toHaveBeenCalledWith('Email address is required to sign in');
});
test('Errors when no password is input', () => {
jest.spyOn(window, 'alert').mockImplementation(() => {});
const wrapper = shallow(<SignInForm />);
wrapper.find('input#email_address').simulate('change', {target: { value: "Tst@test.com" }});
wrapper.find('button').simulate('click');
expect(window.alert).toHaveBeenCalledWith('Email address is required to sign in');
});
登录表单Web组件:
import React, {Component} from 'react';
export default class SignInForm extends Component {
constructor(props) {
super(props);
this.state = {email_address: '', password: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(field, event) {
this.setState({[field]: event.target.value});
}
handleSubmit(event) {
if (event) {
event.preventDefault();
}
const {email_address, password} = this.state;
if (email_address === '') {
alert("Email address is required to sign in");
return;
} else if (password === '') {
alert("Password is required to sign in");
return;
}
}
render() {
return (
<form id="signInForm">
<div className="form-group">
<label htmlFor="email_address">Email address</label>
<input type="email" className="form-control" name="email_address" id="email_address"
aria-describedby="emailHelp" placeholder="Enter email" onChange={this.handleChange.bind(null, 'email_address')} />
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input type="password" className="form-control" id="password" name="password" placeholder="Password" onChange={this.handleChange.bind(null, 'password')} />
</div>
<button type="submit" className="btn btn-primary" onClick={this.handleSubmit.bind(this)}>Submit</button>
</form >
);
}
}
答案 0 :(得分:0)
这是因为开玩笑在内部跟踪正在发生的一切。如果它运行一次(从您的第一个测试开始),它将“记住”第二个测试运行的时间。我敢打赌,如果您更改这两个测试的顺序,它们将通过。但这不是真正的解决方案。
运行每个测试之前,您必须先jest.clearAllMocks()
。您应该将所有测试划分为一个describe
块,并在其中运行beforeEach
,以便可以在每次测试之前自动运行jest.clearAllMocks()
。
describe('unit tests', () => ({
beforeEach(() => {
jest.clearAllMocks()
})
// test('Errors when no email is input', () => { unit tests here
})