在create-react-app中用Enzyme测试React/Redux组件遇报错求助
Hey Olivia, let's break down those two test errors you're facing and fix them step by step—they're totally common when getting started with Enzyme, Jest, and Redux in a Create React App, so you're not alone here!
First Error: TypeError: Cannot read property 'length' of undefined
This almost always happens because your App component is trying to access the length property of a value that's undefined in your test environment. Since you're using Redux, it's likely that your component gets a list/array from the store via mapStateToProps, but your test isn't providing an initialized store (or mock props) with that data.
Fixes:
You have two straightforward options here:
Option 1: Pass mock props directly to the component
If you just want to test the component's rendering without Redux integration, simulate the props that Redux would normally pass down:// In your App.test.js import { shallow } from 'enzyme'; import App from './App'; it('renders without crashing', () => { // Mock the props your component expects from Redux const mockProps = { items: ['first item', 'second item'], // Replace with your actual state shape nextItem: jest.fn() // Mock the action creator }; shallow(<App {...mockProps} />); });Option 2: Wrap the component with a Redux Provider and mock store
If you want to test the Redux integration, use a mock store to provide initial state:import { shallow } from 'enzyme'; import { Provider } from 'react-redux'; import configureStore from 'redux-mock-store'; import App from './App'; const mockStore = configureStore([]); // Initialize mock store with middleware (empty array if none) it('renders without crashing', () => { const initialState = { items: ['first item', 'second item'] // Match your actual root state shape }; const store = mockStore(initialState); shallow( <Provider store={store}> <App /> </Provider> ); });
Second Error: TypeError: Cannot read property 'have' of undefined
This is a syntax mismatch between assertion libraries. You're probably using Chai-style assertions (like to.have.length) but Create React App uses Jest's built-in assertions by default, which don't use that chainable have syntax.
Fixes:
Switch to Jest's native assertion syntax
Replace Chai-style lines with Jest equivalents:// ❌ Wrong (Chai style) expect(wrapper.find('button')).to.have.length(1); // ✅ Correct (Jest style) expect(wrapper.find('button')).toHaveLength(1);Other common replacements:
to.have.text()→toHaveTextContent()to.have.prop('disabled')→toHaveProp('disabled')
Double-check your Enzyme adapter setup
Make sure you've configured the Enzyme adapter correctly insrc/setupTests.js(this file runs automatically before tests in Create React App):import { configure } from 'enzyme'; import Adapter from 'enzyme-adapter-react-15'; configure({ adapter: new Adapter() });Without this setup, Enzyme's methods might behave unpredictably, leading to weird assertion errors.
Testing the "Next Item" Click Function
Once the above errors are fixed, here's how to test the click functionality:
// Example with mock props it('triggers nextItem when the button is clicked', () => { const mockNextItem = jest.fn(); const wrapper = shallow(<App items={['item1', 'item2']} nextItem={mockNextItem} />); // Simulate the button click wrapper.find('button').simulate('click'); // Verify the mock function was called expect(mockNextItem).toHaveBeenCalledTimes(1); }); // Example with Redux mock store it('dispatches the NEXT_ITEM action on button click', () => { const store = mockStore({ items: ['item1', 'item2'] }); const wrapper = mount( <Provider store={store}> <App /> </Provider> ); wrapper.find('button').simulate('click'); // Check if the correct action was dispatched const actions = store.getActions(); expect(actions).toEqual([{ type: 'NEXT_ITEM' }]); // Replace with your action type });
Just double-check that your mock state/props match the shape your component expects, and you should be good to go!
内容的提问来源于stack exchange,提问作者Olivia

