不能监视原始值; undefined given - 在连接组件的 onChange 中测试函数执行
Cannot spyOn on a primitive value; undefined given - Testing a function execution in onChange in connected component
测试新手,这是一个使用 redux 的连接组件。我正在测试是否调用了 maskPromoCode 函数。使用当前的测试代码,错误显示:无法监视原始值;给定未定义
不明白为什么。谢谢
组件:
class Textbox extends React.Component {
constructor(props) {
super(props);
}
onChange(e) {
e.preventDefault();
this.setState({
value: this.maskPromoCode(e.target.value)
})
}
maskPromoCode(value) {...}
render() {
return (
<>
<input
...
onChange={e => this.onChange(e)}
/>
</>
);
}
}
const mapDispatchToProps = { setError, setPwError };
export default connect(null, mapDispatchToProps)(Textbox);
测试文件
it('invokes the maskPromoCode function with event value', () => {
const funcMock = jest.spyOn(Textbox.prototype, 'maskPromoCode');
const wrapper = mount(
<Provider store={store}>
<Textbox {...baseProps} name="redeem-promo" />
</Provider>
);
const inputField = wrapper.find('input');
const event = {
target: {
value: 'event value',
},
};
inputField.simulate('change', event);
expect(funcMock).toHaveBeenCalledWith(event.target.value);
});
Textbox
组件被connect
函数包裹,变成了没有prototype
的HOC,我猜你在测试中导入了HOC文件。测试文件中导入的 TextBox
组件是一个 HOC。所以 TextBox.prototype
是 undefined
,这就是 jest.spyOn
抛出错误的原因。
maskPromoCode
方法如果坚持要用jest.spyOn()
,可以用jest.spyOn(Textbox.WrappedComponent.prototype, 'maskPromoCode')
。 HOC上有一个WrappedComponent static 属性,所以可以得到原始组件class.
建议:如果使用 jest.spyOn(...)
,您正在测试实现细节,您应该测试组件行为。
例如
Textbox.jsx
:
import React from 'react';
import { connect } from 'react-redux';
class Textbox extends React.Component {
constructor(props) {
super(props);
this.state = { value: '131' };
}
onChange(e) {
e.preventDefault();
this.setState({ value: this.maskPromoCode(e.target.value) });
}
maskPromoCode(value) {
return '***';
}
render() {
return (
<>
<input value={this.state.value} onChange={(e) => this.onChange(e)} />
</>
);
}
}
export default connect(null, null)(Textbox);
Textbox.test.jsx
:
import Textbox from './Textbox';
import React from 'react';
import configureStore from 'redux-mock-store';
import { Provider } from 'react-redux';
describe('70795348', () => {
it('invokes the maskPromoCode function with event value', () => {
console.log(Textbox.WrappedComponent.prototype.maskPromoCode);
const mockStore = configureStore();
const store = mockStore();
const wrapper = mount(
<Provider store={store}>
<Textbox name="redeem-promo" />
</Provider>
);
expect(wrapper.find('input').instance().value).toBe('131');
const event = { target: { value: 'event value' } };
wrapper.find('input').simulate('change', event);
expect(wrapper.find('input').instance().value).toBe('***');
});
});
测试结果:
PASS Whosebug/70795348/Textbox.test.jsx
70795348
✓ invokes the maskPromoCode function with event value (40 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.729 s, estimated 9 s
测试新手,这是一个使用 redux 的连接组件。我正在测试是否调用了 maskPromoCode 函数。使用当前的测试代码,错误显示:无法监视原始值;给定未定义
不明白为什么。谢谢
组件:
class Textbox extends React.Component {
constructor(props) {
super(props);
}
onChange(e) {
e.preventDefault();
this.setState({
value: this.maskPromoCode(e.target.value)
})
}
maskPromoCode(value) {...}
render() {
return (
<>
<input
...
onChange={e => this.onChange(e)}
/>
</>
);
}
}
const mapDispatchToProps = { setError, setPwError };
export default connect(null, mapDispatchToProps)(Textbox);
测试文件
it('invokes the maskPromoCode function with event value', () => {
const funcMock = jest.spyOn(Textbox.prototype, 'maskPromoCode');
const wrapper = mount(
<Provider store={store}>
<Textbox {...baseProps} name="redeem-promo" />
</Provider>
);
const inputField = wrapper.find('input');
const event = {
target: {
value: 'event value',
},
};
inputField.simulate('change', event);
expect(funcMock).toHaveBeenCalledWith(event.target.value);
});
Textbox
组件被connect
函数包裹,变成了没有prototype
的HOC,我猜你在测试中导入了HOC文件。测试文件中导入的TextBox
组件是一个 HOC。所以TextBox.prototype
是undefined
,这就是jest.spyOn
抛出错误的原因。maskPromoCode
方法如果坚持要用jest.spyOn()
,可以用jest.spyOn(Textbox.WrappedComponent.prototype, 'maskPromoCode')
。 HOC上有一个WrappedComponent static 属性,所以可以得到原始组件class.建议:如果使用
jest.spyOn(...)
,您正在测试实现细节,您应该测试组件行为。
例如
Textbox.jsx
:
import React from 'react';
import { connect } from 'react-redux';
class Textbox extends React.Component {
constructor(props) {
super(props);
this.state = { value: '131' };
}
onChange(e) {
e.preventDefault();
this.setState({ value: this.maskPromoCode(e.target.value) });
}
maskPromoCode(value) {
return '***';
}
render() {
return (
<>
<input value={this.state.value} onChange={(e) => this.onChange(e)} />
</>
);
}
}
export default connect(null, null)(Textbox);
Textbox.test.jsx
:
import Textbox from './Textbox';
import React from 'react';
import configureStore from 'redux-mock-store';
import { Provider } from 'react-redux';
describe('70795348', () => {
it('invokes the maskPromoCode function with event value', () => {
console.log(Textbox.WrappedComponent.prototype.maskPromoCode);
const mockStore = configureStore();
const store = mockStore();
const wrapper = mount(
<Provider store={store}>
<Textbox name="redeem-promo" />
</Provider>
);
expect(wrapper.find('input').instance().value).toBe('131');
const event = { target: { value: 'event value' } };
wrapper.find('input').simulate('change', event);
expect(wrapper.find('input').instance().value).toBe('***');
});
});
测试结果:
PASS Whosebug/70795348/Textbox.test.jsx
70795348
✓ invokes the maskPromoCode function with event value (40 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.729 s, estimated 9 s