reactjs - para - Pruebas de componentes anidados con enzima dentro de React & Redux
react native redux ejemplo (6)
Tengo un componente SampleComponent
que monta otro "componente conectado" (es decir, un container
). Cuando intento probar SampleComponent
mount
(ya que necesito el componentDidMount
), obtengo el error:
Violación invariante: no se pudo encontrar "almacén" en el contexto o en los accesorios de "Conectar (ContainerComponent)". O envuelva el componente raíz en una, o pase explícitamente "store" como prop para "Connect (ContainerComponent)".
¿Cuál es la mejor manera de probar esto?
Opción 1)
Puede envolver el componente contenedor con el componente Proveedor de React-Redux dentro de su prueba. Así que con este enfoque, usted realmente hace referencia a la tienda, se la pasa al Proveedor y compone su componente bajo prueba en su interior. La ventaja de este enfoque es que realmente puede crear un almacén personalizado para la prueba. Este enfoque es útil si desea probar las partes de su componente relacionadas con Redux.
Opcion 2)
Tal vez no te importa probar las piezas relacionadas con Redux. Si simplemente está interesado en probar la representación del componente y los comportamientos locales relacionados con el estado, puede simplemente agregar una exportación con nombre para la versión simple no conectada de su componente. Y solo para aclarar cuando agrega la palabra clave "exportar" a su clase, básicamente está diciendo que ahora la clase se puede importar de 2 maneras, ya sea con llaves {} o no. ejemplo:
export class MyComponent extends React.Component{ render(){ ... }}
...
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
más tarde en su archivo de prueba:
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.
Espero que ayude a alguien por ahí.
El montaje de la enzima toma parámetros opcionales. Los dos que son necesarios para lo que necesitas son.
options.context: (Object [optional]): Context to be passed into the component
options.childContextTypes: (Object [optional]): Merged contextTypes for all children of the wrapper
SampleComponent
options.childContextTypes: (Object [optional]): Merged contextTypes for all children of the wrapper
. SampleComponent
montar SampleComponent
con un objeto de opciones así:
const store = {
subscribe: () => {},
dispatch: () => {},
getState: () => ({ ... whatever state you need to pass in ... })
}
const options = {
context: { store },
childContextTypes: { store: React.PropTypes.object.isRequired }
}
const _wrapper = mount(<SampleComponent {...defaultProps} />, options)
Ahora su SampleComponent pasará el contexto que proporcionó al connected component
.
En un intento por hacer más comprobable el uso de la sintaxis del decorador, hice esto: https://www.npmjs.com/package/babel-plugin-undecorate
entrada:
@anyOldClassDecorator
export class AnyOldClass {
@anyOldMethodDecorator
method() {
console.log(''hello'');
}
}
salida:
@anyOldClassDecorator
export class AnyOldClass {
@anyOldMethodDecorator
method() {
console.log(''hello'');
}
}
export class __undecorated__AnyOldClass {
method() {
console.log(''hello'');
}
}
¡Esperemos que esto pueda proporcionar una sólida opción 3 !
Lo que esencialmente hice fue traer mi tienda de redux
(y Provider
) y envolverla en un componente de utilidad de la siguiente manera:
export const CustomProvider = ({ children }) => {
return (
<Provider store={store}>
{children}
</Provider>
);
};
luego, mount
el SampleComponent
y ejecuto pruebas contra él:
it(''contains <ChildComponent/> Component'', () => {
const wrapper = mount(
<CustomProvider>
<SampleComponent {...defaultProps} />
</CustomProvider>
);
expect(wrapper.find(ChildComponent)).to.have.length(1);
});
Puedes usar la exportación de nombres para resolver este problema:
Deberías:
class SampleComponent extends React.Component{
...
render(){
<div></div>
}
}
export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent)
Puedes agregar una exportación antes de la clase:
export class SampleComponent extends React.Component{
e importe este componente sin redux store:
import { SampleComponent } from ''your-path/SampleComponent'';
Con esta solución, no es necesario importar la tienda a sus archivos de prueba.
También existe la opción de usar redux-mock-store .
Una tienda simulada para probar los creadores de acción asíncrona de Redux y middleware El almacén simulado creará una serie de acciones enviadas que sirven como un registro de acciones para las pruebas.
El almacén simulado proporciona los métodos necesarios en el objeto de la tienda que se requieren para Redux. Puede especificar middlewares opcionales y el estado inicial específico de su aplicación.
import configureStore from ''redux-mock-store'' const middlewares = [] const mockStore = configureStore(middlewares) const initialState = {} const store = mockStore(initialState) const wrapper = mount(<SampleComponent store={store}/>)