我试图用Jest对我的React组件进行单元测试。我的测试通过了,但是由于try / catch中的console.error()导致出现TypeError。我认为我的模拟程序设置不正确,但是我尝试将其与任何结果保持异步。我感谢所有提示。
console.error组件/App.js:91 TypeError:无法读取未定义的属性“ fetchPoints” 在App.fetchPoints(D:\\ components \ App.js:87:48) 在tryCatch(D:\\ node_modules \ regenerator-runtime \ runtime.js:62:40) 在Generator.invoke上[作为_invoke](D:\\ node_modules \ regenerator-runtime \ runtime.js:296:22) 在Generator.prototype。(匿名函数)[下一个](D:\\ node_modules \ regenerator-runtime \ runtime.js:114:21) 在步骤(D:\\ components \ App.js:38:191) 在D:\\ components \ App.js:38:437 在新的Promise() 在应用程序上。 (D:\\ components \ App.js:38:99) 在App.componentDidMount(D:\\ components \ App.js:155:30) 在D:\\ node_modules \ react-test-renderer \ lib \ ReactCompositeComponent.js:262:25 在measureLifeCyclePerf(D:\\ node_modules \ react-test-renderer \ lib \ ReactCompositeComponent.js:73:12) 在D:\\ node_modules \ react-test-renderer \ lib \ ReactCompositeComponent.js:261:11 在CallbackQueue.notifyAll(D:\\ node_modules \ react-test-renderer \ lib \ CallbackQueue.js:74:22) 在ReactTestReconcileTransaction.close(D:\\ node_modules \ react-test-renderer \ lib \ ReactTestReconcileTransaction.js:34:26) 在ReactTestReconcileTransaction.closeAll(D:\\ node_modules \ react-test-renderer \ lib \ Transaction.js:207:25) 在ReactTestReconcileTransaction.perform(D:\\ node_modules \ react-test-renderer \ lib \ Transaction.js:154:16) 在batchedMountComponentIntoNode(D:\\ node_modules \ react-test-renderer \ lib \ ReactTestMount.js:67:27) 在ReactDefaultBatchingStrategyTransaction.perform(D:\\ node_modules \ react-test-renderer \ lib \ Transaction.js:141:20) 在Object.batchedUpdates(D:\\ node_modules \ react-test-renderer \ lib \ ReactDefaultBatchingStrategy.js:60:26) 在Object.batchedUpdates(D:\\ node_modules \ react-test-renderer \ lib \ ReactUpdates.js:95:27) 在Object.render(D:\\ node_modules \ react-test-renderer \ lib \ ReactTestMount.js:126:18) 在Object.create(D:\\ components__tests __ \ App.test.js:26:31) 在Object.asyncJestTest(D:\\ node_modules \ jest-jasmine2 \ build \ jasmine_async.js:108:37) 解析时(D:\\ node_modules \ jest-jasmine2 \ build \ queue_runner.js:56:12) 在新的Promise() 在映射器上(D:\\ node_modules \ jest-jasmine2 \ build \ queue_runner.js:43:19) 然后承诺(D:\\ node_modules \ jest-jasmine2 \ build \ queue_runner.js:87:41) 在 在process._tickCallback(internal / process / next_tick.js:188:7)
App.test.js
我试图使用mount()和fetchPoints返回Promise.resolve()。
import React from 'react';
import renderer from 'react-test-renderer';
import { shallow, configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-15';
import { App } from '../App';
configure({ adapter: new Adapter() });
describe('App', () => {
let wrapper;
const apiMockActions = {
fetchPoints : jest.fn()
};
beforeEach(() => {
wrapper = shallow(<App actions={apiMockActions} />);
});
it('should call fetchPoints in #componentDidMount', () => {
return wrapper.instance().componentDidMount().then(() => {
expect(apiMockActions.fetchPoints).toHaveBeenCalled();
});
});
});
App.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as api from '../actions/api';
import { bindActionCreators } from 'redux';
export class App extends Component {
constructor(props){
super(props);
this.state = {
data: []
}
}
async componentDidMount() {
try {
let res = await this.props.actions.fetchPoints();
//this.setState({ data: res });
} catch (error) {
console.error(error);
}
}
render() {
return (
<div className="col-md-12 app__div">
</div>
);
}
}
function mapStateToProps(state) {
return {
data: state.points
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Object.assign({}, api), dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
package.json
"dependencies": {
"ag-grid": "^14.2.0",
"ag-grid-react": "^14.2.0",
"axios": "^0.16.2",
"babel-eslint": "^8.2.6",
"babel-polyfill": "^6.26.0",
"chart.js": "^2.7.1",
"classnames": "^2.2.5",
"eslint": "^5.2.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-react": "^7.10.0",
"lodash": "^4.15.0",
"moment": "^2.19.3",
"prop-types": "^15.6.0",
"rc-time-picker": "^2.4.1",
"react": "^15.6.2",
"react-addons-css-transition-group": "^15.6.2",
"react-autosuggest": "^9.3.2",
"react-bootstrap": "^0.31.5",
"react-color": "^2.14.0",
"react-datalist": "^4.0.0",
"react-datepicker": "^0.29.0",
"react-dom": "^15.6.2",
"react-dom-factories": "^1.0.2",
"react-dropzone": "^3.13.4",
"react-grid-layout": "^0.15.3",
"react-intl": "^2.4.0",
"react-notification-system": "^0.2.16",
"react-notify": "^2.0.1",
"react-redux": "^5.0.6",
"react-timepicker": "^1.3.1",
"react-toggle-display": "^2.2.0",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-promise-middleware": "^4.4.2",
"redux-thunk": "^2.2.0",
"section-iterator": "^2.0.0",
"style-loader": "^0.13.2"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-jest": "^23.4.0",
"babel-loader": "^7.1.2",
"babel-plugin-lodash": "^3.3.2",
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-preset-env": "^1.6.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"chalk": "^2.3.0",
"cross-env": "^5.1.1",
"css-loader": "^0.23.1",
"enzyme": "^3.3.0",
"enzyme-adapter-react-15": "^1.0.6",
"jest": "^23.4.1",
"jest-cli": "^23.4.1",
"parallel-webpack": "^1.5.0",
"progress-bar-webpack-plugin": "^1.11.0",
"react-test-renderer": "^15.6.2",
"redux-immutable-state-invariant": "^2.1.0",
"style-loader": "^0.13.1",
"webpack": "^4.16.1",
"webpack-cli": "^3.0.8"
},
答案 0 :(得分:1)
应该为每个测试创建间谍和存根:
let apiMockActions;
beforeEach(() => {
apiMockActions = {
fetchPoints : jest.fn()
};
});
生命周期默认情况下在酶3和更高版本中处于启用状态,因此手动调用componentDidMount
将导致两次调用。他们can be disabled为了链接来自componentDidMount
的承诺:
beforeEach(() => {
wrapper = shallow(<App actions={apiMockActions} />, { disableLifecycleMethods: true });
});
可以用mockResolvedValue
模拟返回的承诺值:
it('should call fetchPoints in #componentDidMount', async () => {
const points = [...];
const instance = wrapper.instance();
apiMockActions.fetchPoints.mockResolvedValue(points);
await instance.componentDidMount();
expect(apiMockActions.fetchPoints).toHaveBeenCalled();
expect(instance.state.data).toEqual({ data: points });
});