Ayu*_*hya 48 unit-testing mocha.js sinon reactjs redux
我正在使用Mocha,Chai,Karma,Sinon,Webpack进行单元测试.
我按照此链接配置了React-Redux Code的测试环境.
我可以成功测试我的动作和reducers javascript代码,但是当涉及到测试我的组件时,它总是会产生一些错误.
import React from 'react';
import TestUtils from 'react/lib/ReactTestUtils'; //I like using the Test Utils, but you can just use the DOM API instead.
import chai from 'chai';
// import sinon from 'sinon';
import spies from 'chai-spies';
chai.use(spies);
let should = chai.should()
, expect = chai.expect;
import { PhoneVerification } from '../PhoneVerification';
let fakeStore = {
'isFetching': false,
'usernameSettings': {
'errors': {},
'username': 'sahil',
'isEditable': false
},
'emailSettings': {
'email': 'test@test.com',
'isEmailVerified': false,
'isEditable': false
},
'passwordSettings': {
'errors': {},
'password': 'showsomestarz',
'isEditable': false
},
'phoneSettings': {
'isEditable': false,
'errors': {},
'otp': null,
'isOTPSent': false,
'isOTPReSent': false,
'isShowMissedCallNumber': false,
'isShowMissedCallVerificationLink': false,
'missedCallNumber': null,
'timeLeftToVerify': null,
'_verifiedNumber': null,
'timers': [],
'phone': '',
'isPhoneVerified': false
}
}
function setup () {
console.log(PhoneVerification);
// PhoneVerification.componentDidMount = chai.spy();
let output = TestUtils.renderIntoDocument(<PhoneVerification {...fakeStore}/>);
return {
output
}
}
describe('PhoneVerificationComponent', () => {
it('should render properly', (done) => {
const { output } = setup();
expect(PhoneVerification.prototype.componentDidMount).to.have.been.called;
done();
})
});
Run Code Online (Sandbox Code Playgroud)
以上代码出现以下错误.
FAILED TESTS:
PhoneVerificationComponent
? should render properly
Chrome 48.0.2564 (Mac OS X 10.11.3)
Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
Run Code Online (Sandbox Code Playgroud)
试图从sinon间谍转向chai-spies.
我应该如何对我的React-Redux连接组件(智能组件)进行单元测试?
Ash*_*ijk 48
一个更漂亮的方法是导出普通组件和连接中包含的组件.命名导出将是组件,默认是包装组件:
export class Sample extends Component {
render() {
let { verification } = this.props;
return (
<h3>This is my awesome component.</h3>
);
}
}
const select = (state) => {
return {
verification: state.verification
}
}
export default connect(select)(Sample);
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以在应用程序中正常导入,但在测试时,您可以使用导入命名导出import { Sample } from 'component'.
Joh*_*nSz 14
您可以测试连接的组件,我认为您应该这样做.您可能希望首先测试未连接的组件,但我建议您在没有测试连接组件的情况下也不会有完整的测试覆盖率.
下面是我对Redux和Enzyme做的未经测试的提取物.中心思想是使用Provider将测试中的状态连接到测试中的连接组件.
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import SongForm from '../SongForm'; // import the CONNECTED component
// Use the same middlewares you use with Redux's applyMiddleware
const mockStore = configureMockStore([ /* middlewares */ ]);
// Setup the entire state, not just the part Redux passes to the connected component.
const mockStoreInitialized = mockStore({
songs: {
songsList: {
songs: {
songTags: { /* ... */ }
}
}
}
});
const nullFcn1 = () => null;
const nullFcn2 = () => null;
const nullFcn3 = () => null;
const wrapper = mount( // enzyme
<Provider store={store}>
<SongForm
screen="add"
disabled={false}
handleFormSubmit={nullFcn1}
handleModifySong={nullFcn2}
handleDeleteSong={nullFcn3}
/>
</Provider>
);
const formPropsFromReduxForm = wrapper.find(SongForm).props(); // enzyme
expect(
formPropsFromReduxForm
).to.be.deep.equal({
screen: 'add',
songTags: initialSongTags,
disabled: false,
handleFormSubmit: nullFcn1,
handleModifySong: nullFcn2,
handleDeleteSong: nullFcn3,
});
===== ../SongForm.js
import React from 'react';
import { connect } from 'react-redux';
const SongForm = (/* object */ props) /* ReactNode */ => {
/* ... */
return (
<form onSubmit={handleSubmit(handleFormSubmit)}>
....
</form>
};
const mapStateToProps = (/* object */ state) /* object */ => ({
songTags: state.songs.songTags
});
const mapDispatchToProps = () /* object..function */ => ({ /* ... */ });
export default connect(mapStateToProps, mapDispatchToProps)(SongForm)
Run Code Online (Sandbox Code Playgroud)
您可能想要使用纯Redux创建商店.redux-mock-store只是一个轻量级版本,用于测试.
您可能希望使用react-addons-test-utils而不是airbnb的Enzyme.
我使用airbnb的chai-enzyme来获得React-aware expect选项.在这个例子中不需要它.
可接受的答案的问题在于,我们只是为了进行测试而不必要地导出了某些内容。在我看来,导出类只是为了测试它不是一个好主意。
这是一个更整洁的解决方案,除了连接的组件外,无需导出任何内容:
如果使用的是笑话,则可以模拟connect方法返回三件事:
这样做非常简单。有两种方法:内联模拟或全局模拟。
1.使用内联模拟
在测试的describe函数之前添加以下代码段。
jest.mock('react-redux', () => {
return {
connect: (mapStateToProps, mapDispatchToProps) => (ReactComponent) => ({
mapStateToProps,
mapDispatchToProps,
ReactComponent
}),
Provider: ({ children }) => children
}
})Run Code Online (Sandbox Code Playgroud)
2.使用文件模拟
__mocks__/react-redux.js在根目录(package.json所在的位置)中创建一个文件module.exports = {
connect: (mapStateToProps, mapDispatchToProps) => (ReactComponent) => ({
mapStateToProps,
mapDispatchToProps,
ReactComponent,
}),
Provider: ({children}) => children
};Run Code Online (Sandbox Code Playgroud)
嘲讽之后,你就可以访问所有使用上述三种Container.mapStateToProps,Container.mapDispatchToProps和Container.ReactComponent。
只需简单地导入容器即可
import Container from '<path>/<fileName>.container.js'
希望能帮助到你。
请注意,如果您使用文件模拟。模拟文件将在所有测试用例中全局使用(除非jest.unmock('react-redux'))在测试用例之前执行此操作)。
编辑:我写了一个详细的博客,上面详细解释了:
| 归档时间: |
|
| 查看次数: |
21274 次 |
| 最近记录: |