J'ai un composant SampleComponent
qui monte un autre "composant connecté" (c'est-à-dire container
). Lorsque j'essaie de tester SampleComponent
par mount
ing (car j'ai besoin de componentDidMount
), j'obtiens le message d'erreur
Violation invariante: Impossible de trouver "magasin" dans le contexte ou les accessoires de "Connect (ContainerComponent)". Soit envelopper le composant racine dans un ou explicitement passer "magasin" comme accessoire à "Connect (ContainerComponent)".
Quelle est la meilleure façon de tester cela?
Ce que j’ai essentiellement fait, c’est d’apporter mon magasin redux
(et Provider
) et de le placer dans un composant utilitaire comme suit:
export const CustomProvider = ({ children }) => {
return (
<Provider store={store}>
{children}
</Provider>
);
};
alors, je mount
la SampleComponent
et lance des tests pour la comparer:
it('contains <ChildComponent/> Component', () => {
const wrapper = mount(
<CustomProvider>
<SampleComponent {...defaultProps} />
</CustomProvider>
);
expect(wrapper.find(ChildComponent)).to.have.length(1);
});
Vous pouvez utiliser l'export de noms pour résoudre ce problème:
Tu aurais dû:
class SampleComponent extends React.Component{
...
render(){
<div></div>
}
}
export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent)
Vous pouvez ajouter une exportation avant le cours:
export class SampleComponent extends React.Component{
et importer ce composant sans magasin Redux:
import { SampleComponent } from 'your-path/SampleComponent';
Avec cette solution, vous n'avez pas besoin d'importer le magasin dans vos fichiers de test.
Vous pouvez encapsuler le composant conteneur avec le composant fournisseur de React-Redux dans votre test. Ainsi, avec cette approche, vous référencez réellement le magasin, vous le transmettez au fournisseur et composez votre composant à tester à l'intérieur. L'avantage de cette approche est que vous pouvez créer un magasin personnalisé pour le test. Cette approche est utile si vous souhaitez tester les parties de votre composant liées à Redux.
Peut-être que vous ne vous souciez pas de tester les morceaux liés à Redux. Si vous souhaitez simplement tester le comportement du composant et les comportements liés à l'état local du composant, vous pouvez simplement ajouter une exportation nommée pour la version brute non connectée de votre composant. Et juste pour préciser quand vous ajoutez le mot-clé "export" à votre classe, vous dites que la classe peut maintenant être importée de 2 manières, avec des accolades {} ou non. Exemple:
export class MyComponent extends React.Component{ render(){ ... }}
...
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
plus tard sur votre fichier de test:
import MyComponent from 'your-path/MyComponent'; // it needs a store because you use "default export" with connect
import {MyComponent} from 'your-path/MyComponent'; // don't need store because you use "export" on top of your class.
J'espère aider quelqu'un.
Il existe également la possibilité d'utiliser redux-mock-store .
Un magasin factice pour tester les créateurs d’actions asynchrones et les middlewares Redux. Le magasin fictif créera un tableau d'actions envoyées servant de journal des actions pour les tests.
Le magasin fictif fournit les méthodes nécessaires sur l'objet magasin qui sont requises pour Redux . Vous pouvez spécifier des middlewares facultatifs et l'état initial de votre application.
import configureStore from 'redux-mock-store'
const middlewares = []
const mockStore = configureStore(middlewares)
const initialState = {}
const store = mockStore(initialState)
const wrapper = mount(<SampleComponent store={store}/>)
dans le but de rendre l'utilisation de la syntaxe de décorateur plus testable, j'ai ajouté ceci: https://www.npmjs.com/package/babel-plugin-undecorate
contribution:
@anyOldClassDecorator
export class AnyOldClass {
@anyOldMethodDecorator
method() {
console.log('hello');
}
}
sortie:
@anyOldClassDecorator
export class AnyOldClass {
@anyOldMethodDecorator
method() {
console.log('hello');
}
}
export class __undecorated__AnyOldClass {
method() {
console.log('hello');
}
}
J'espère que cela peut fournir un solide Option 3!