2016-06-13 5 views
21

Ich habe eine Komponente SampleComponent, die eine andere "verbundene Komponente" (d. H. container) montiert. Wenn ich versuche, SampleComponent durch mount ing zu testen (da ich die componentDidMount brauchen), erhalte ich die Fehlermeldung:Verschachtelte Komponenten testen mit Enzym innerhalb von React & Redux

Invariant Violation: Could not find "store" in either the context or props of "Connect(ContainerComponent)". Either wrap the root component in a , or explicitly pass "store" as a prop to "Connect(ContainerComponent)".

Was ist der beste Weg, dies zu testen?

Antwort

4

Was ich im Wesentlichen in meinem redux Laden tat, war bringen (und Provider) und wickelte ihn in ein Dienstprogramm Komponente wie folgt:

export const CustomProvider = ({ children }) => { 
    return (
    <Provider store={store}> 
     {children} 
    </Provider> 
); 
}; 

dann, mount ich die SampleComponent und führen Tests dagegen:

it('contains <ChildComponent/> Component',() => { 
    const wrapper = mount(
    <CustomProvider> 
     <SampleComponent {...defaultProps} /> 
    </CustomProvider> 
); 
    expect(wrapper.find(ChildComponent)).to.have.length(1); 
}); 
+0

Ich sehe Sie verwenden mount, wenn ich versuche, '' mount'' durch '' shallo'' zu ersetzen bekomme ich einen Fehler. Ist dir das auch schon begegnet? – Mehrdad

+2

Während diese Antwort in einigen Fällen funktioniert, funktioniert sie nicht, wenn Sie den Lebenszyklus Ihrer Komponente testen müssen. Wenn Sie zum Beispiel 'wrapper.setProps()' aufrufen, wird 'componentWillReceiveProps()' auf 'SampleComponent' nicht ausgelöst. –

25

Die Halterung des Enzyms benötigt optionale Parameter. Die beiden, die notwendig sind für das, was Sie brauchen, sind

options.context: (Object [optional]): Context to be passed into the component

options.childContextTypes: (Object [optional]): Merged contextTypes for all children of the wrapper Sie würden montieren SampleComponent mit einem Optionen-Objekt wie folgt:

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) 

Jetzt ist Ihre Sample den Kontext übergeben Sie zur Verfügung gestellt unten zu die .

+2

Das ist perfekt! Während die angenommene Antwort die meiste Zeit funktioniert, ist der Nachteil, dass Sie die Fähigkeit verlieren, die mount api zu seiner vollen Kapazität zu verwenden. Zum Beispiel erlaubt es die akzeptierte Antwort, die Komponente in einen "Provider" zu verpacken, nicht, die 'wrapper.state()' API zu verwenden. Diese Lösung bietet Ihnen die vollständige Palette an Methoden für Ihren Wrapper. – neurosnap

+0

Dies ist eine bessere Antwort als die angenommene Antwort, aus den oben genannten Gründen (dh Ihr eingehängter Wrapper ist nicht wirklich die Komponente, die Sie versuchen zu testen), und auch weil Sie dann einen Scheinspeicher anstelle Ihres tatsächlichen Geschäftes verwenden können alles von redux aus der Gleichung. – GTF

+2

Dieses optionale Argument ist nicht in der Dokumentation, wie haben Sie es gefunden? im Code? –

1

Sie Namen exportieren können, dieses Problem zu lösen:

Sie haben sollten:

class SampleComponent extends React.Component{ 
... 
    render(){ 
     <div></div> 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent) 

Sie einen Export vor der Klasse hinzufügen:

export class SampleComponent extends React.Component{ 

und importieren diese Komponente mit nicht redux Geschäft:

import { SampleComponent } from 'your-path/SampleComponent'; 

Mit dieser Lösung müssen Sie den Speicher nicht in Ihre Testdateien importieren.

1

Option 1) Sie können die Containerkomponente mit der Provider-Komponente von React-Redux innerhalb Ihres Tests umbrechen. Bei diesem Ansatz referenzieren Sie den Store, übergeben ihn an den Provider und komponieren Ihre zu testende Komponente darin. Der Vorteil dieses Ansatzes besteht darin, dass Sie tatsächlich einen benutzerdefinierten Speicher für den Test erstellen können. Dieser Ansatz ist nützlich, wenn Sie die Redux-bezogenen Teile Ihrer Komponente testen möchten. Option 2) Vielleicht interessiert es Sie nicht, die Redux-Teile zu testen. Wenn Sie nur das Rendering und das lokale Statusverhalten der Komponente testen möchten, können Sie einfach einen benannten Export für die nicht verbundene normale Version Ihrer Komponente hinzufügen. Und nur um zu verdeutlichen, wenn Sie das "export" -Schlüsselwort zu Ihrer Klasse hinzufügen, sagen Sie im Grunde, dass die Klasse jetzt auf zwei Arten mit geschweiften Klammern {} importiert werden kann oder nicht. Beispiel:

export class MyComponent extends React.Component{ render(){ ... }} 

... 

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent) 

später auf der Testdatei:

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. 

Ich hoffe, hilft da draußen jemand.

Verwandte Themen