Comment mettre à L'Essai Les composants connectés React-Redux?
J'utilise Mocha, Chai, Karma, Sinon, Webpack pour les tests unitaires.
j'ai suivi ce lien pour configurer mon environnement de test pour le code React-Redux.
je peux tester avec succès mon action et réduire le code javascript, mais quand il s'agit de tester mes composants il lance toujours certains erreur.
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();
})
});
cette erreur suivante apparaît avec le code ci-dessus.
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.
<!-On a essayé de passer des espions aux sinons aux chai-spies.
Comment tester mon Unité de composants connectés React-Redux (composants intelligents)?
4 réponses
Une jolie manière de faire ceci est de l'exporter votre plaine composant et le composant enveloppé dans connect. La nommée à l'exportation serait le composant, la valeur par défaut est le enveloppés composant:
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);
de cette façon vous pouvez importer normalement dans votre application, mais quand il s'agit de tester vous pouvez importer votre exportation nommée en utilisant import { Sample } from 'component'
.
Vous pouvez tester votre composant connecté et je pense que vous devriez le faire. Vous pouvez vouloir tester le composant non connecté d'abord, mais je suggère que vous n'aurez pas la couverture de test complète sans également tester le composant connecté.
ci-dessous est un extrait non testé de ce que je fais avec Redux et Enzyme. L'idée centrale est d'utiliser Provider pour connecter l'état en test au composant connecté en test.
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)
Vous pouvez vouloir créer un magasin avec pure Redux. redux-mock-store est juste une version légère de celui-ci destiné à l'essai.
Vous pouvez utiliser react-addons-test-utils au lieu de l'Enzyme d'airbnb.
j'utilise le chai-enzyme d'airbnb pour avoir des options D'attente réactives. Il n'était pas nécessaire dans cet exemple.
le problème avec la réponse acceptée est que nous exportons quelque chose inutilement juste pour pouvoir le tester. Et exporter une classe juste pour la tester n'est pas une bonne idée à mon avis.
Voici une solution plus nette sans devoir exporter autre chose que le composant connecté:
si vous utilisez jest, vous pouvez vous moquer connect
méthode de retour trois choses:
- mapStateToProps
- mapDispatchToProps
- ReactComponent
le Faire est assez simple. Il y a 2 façons: les moqueries en ligne ou les moqueries globales.
1. En ligne fantaisie
ajouter l'extrait suivant avant la fonction describe du test.
jest.mock('react-redux', () => {
return {
connect: (mapStateToProps, mapDispatchToProps) => (ReactComponent) => ({
mapStateToProps,
mapDispatchToProps,
ReactComponent
}),
Provider: ({ children }) => children
}
})
2. En utilisant le fichier maquette
- Créer un fichier
__mocks__/react-redux.js
à la racine (où l'emballage.json est situé) - ajouter l'extrait suivant dans le fichier.
module.exports = {
connect: (mapStateToProps, mapDispatchToProps) => (ReactComponent) => ({
mapStateToProps,
mapDispatchToProps,
ReactComponent,
}),
Provider: ({children}) => children
};
après vous être moqué, vous pourrez accéder à tous les trois ci-dessus en utilisant Container.mapStateToProps
,Container.mapDispatchToProps
et Container.ReactComponent
.
le conteneur peut être importé en faisant simplement
import Container from '<path>/<fileName>.container.js'
j'Espère que ça aide.
notez que si vous utilisez file mock. Le fichier moqué sera utilisé globalement pour tous les cas de test(sauf si vous faites jest.unmock('react-redux'))
avant l'essai.
essayez de créer 2 fichiers, un avec le composant lui-même, n'étant pas au courant d'aucun magasin ou quoi que ce soit (Phonevérification-component.js). Puis le deuxième (Phonevérification.js), que vous utiliserez dans votre application et qui ne renvoie que le premier composant souscrit à stocker via connect
fonction, quelque chose comme
import PhoneVerificationComponent from './PhoneVerification-component.js'
import {connect} from 'react-redux'
...
export default connect(mapStateToProps, mapDispatchToProps)(PhoneVerificationComponent)
alors vous pouvez tester votre composant "muet" en demandant PhoneVerification-component.js
dans votre test et de lui fournir les accessoires nécessaires moqués. Il ne sert à rien de tester déjà testé (connect decorator, mapStateToProps, mapDispatchToProps etc...)