2016-06-13 19 views
21

Tôi có một thành phần SampleComponent gắn kết một "thành phần được kết nối" khác (ví dụ: container). Khi tôi cố gắng để kiểm tra SampleComponent bởi mount ing (kể từ khi tôi cần componentDidMount), tôi nhận được lỗi:Kiểm tra thành phần lồng nhau với Enzyme bên trong 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)".

cách tốt nhất để thử nghiệm này là gì?

Trả lời

4

Những gì tôi về cơ bản đã được mang trong redux cửa hàng của tôi (và Provider) và bọc nó trong một thành phần tiện ích như sau:

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

sau đó, tôi mount các SampleComponent và chạy thử nghiệm chống lại nó:

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

Tôi thấy bạn đang sử dụng gắn kết, nếu tôi cố gắng thay thế '' gắn kết'' bằng '' shallo'' tôi gặp lỗi. bạn đã gặp phải điều đó chưa? – Mehrdad

+2

Trong khi câu trả lời này hoạt động trong một số trường hợp, nó không hoạt động khi bạn cần kiểm tra vòng đời của thành phần của bạn. Ví dụ, gọi 'wrapper.setProps()' sẽ không kích hoạt 'componentWillReceiveProps()' trên 'SampleComponent'. –

25

Gắn kết của Enzyme có các tham số tùy chọn. Hai đó là cần thiết cho những gì bạn cần là

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

options.childContextTypes: (Object [optional]): Merged contextTypes for all children of the wrapper Bạn sẽ gắn SampleComponent với một lựa chọn đối tượng như vậy:

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) 

Bây giờ SampleComponent bạn sẽ vượt qua bối cảnh mà bạn cung cấp xuống số .

+2

Điều này thật hoàn hảo! Trong khi câu trả lời được chấp nhận hoạt động phần lớn thời gian, nhược điểm là bạn mất khả năng sử dụng api gắn kết với công suất tối đa của nó. Ví dụ, bằng cách sử dụng câu trả lời được chấp nhận của gói thành phần trong một 'Nhà cung cấp' sẽ không cho phép một để sử dụng' wrapper.state() 'api. Giải pháp này sẽ cung cấp cho bạn đầy đủ các phương pháp cho trình bao bọc của bạn. – neurosnap

+0

Đây là câu trả lời tốt hơn câu trả lời được chấp nhận, vì những lý do nêu trên (nghĩa là trình bao bọc của bạn không thực sự là thành phần bạn đang cố kiểm tra), và cũng vì bạn có thể sử dụng kho lưu trữ thay vì cửa hàng thực tế của bạn tất cả các redux ra khỏi phương trình. – GTF

+2

đối số tùy chọn này không có trong tài liệu, làm thế nào bạn tìm thấy nó? trong mã? –

1

Bạn có thể sử dụng xuất khẩu tên để giải quyết vấn đề này:

Bạn nên có:

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

export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent) 

Bạn có thể thêm một xuất khẩu trước khi đến lớp:

export class SampleComponent extends React.Component{ 

và nhập khẩu thành phần này không có redux store:

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

Với giải pháp này, bạn không cần nhập kho lưu trữ vào các tệp thử nghiệm của mình.

1

Tùy chọn 1) Bạn có thể bọc thành phần thùng chứa với thành phần Nhà cung cấp React-Redux trong thử nghiệm của bạn. Vì vậy, với cách tiếp cận này, bạn thực sự tham khảo cửa hàng, chuyển nó cho nhà cung cấp, và soạn thành phần của bạn được thử nghiệm bên trong. Ưu điểm của phương pháp này là bạn thực sự có thể tạo một cửa hàng tùy chỉnh cho thử nghiệm. Cách tiếp cận này rất hữu ích nếu bạn muốn kiểm tra các phần liên quan đến Redux của thành phần của bạn. Tùy chọn 2) Có thể bạn không quan tâm đến việc kiểm tra các phần liên quan đến Redux. Nếu bạn chỉ quan tâm đến việc kiểm tra hiển thị của thành phần và các hành vi liên quan đến trạng thái cục bộ, bạn có thể chỉ cần thêm xuất có tên cho phiên bản thuần túy chưa được kết nối của thành phần của bạn. Và chỉ cần làm rõ khi bạn thêm từ khóa "xuất khẩu" vào lớp của bạn về cơ bản bạn đang nói rằng bây giờ lớp này có thể được nhập bằng 2 cách với dấu ngoặc nhọn {} hay không. Ví dụ:

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

... 

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent) 

sau này tập tin thử nghiệm của bạn:

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. 

tôi hy vọng sẽ giúp mọi người ra khỏi đó.

Các vấn đề liên quan