问题
So I have a component that I import to do some testing with Jest.
class MyComponent extends Component {
render() {
return (
<div>
<OtherComponent />
</div>
);
}
}
export { MyComponent };
where the other component is defined as:
class OtherComponent extends Component { ... }
export default connect(...)(OtherComponent);
My test is as follows:
import React from 'react';
import { shallow } from 'enzyme';
import { MyComponent } from '../../components/MyComponent';
// ...
Just the fact that inside MyComponent there is OtherComponent, that is connected to Redux using connect makes the import above in the test file fail:
Invariant Violation: _registerComponent(...): Target container is not a DOM element.
at invariant (node_modules/fbjs/lib/invariant.js:44:15)
at Object._renderNewRootComponent (node_modules/react-dom/lib/ReactMount.js:311:76)
at Object._renderSubtreeIntoContainer (node_modules/react-dom/lib/ReactMount.js:401:32)
at Object.render (node_modules/react-dom/lib/ReactMount.js:422:23)
at Object.<anonymous> (my-app-directory/index.js:30:46)
at Object.<anonymous> (my-app-directory/components/OtherComponent.js:x:xx)
at Object.<anonymous> (my-app-directory/components/MyComponent.js:x:xx)
at Object.<anonymous> (my-app-directory/test/components/MyComponent.test.js:x:xx)
at handle (node_modules/worker-farm/lib/child/index.js:41:8)
at process.<anonymous> (node_modules/worker-farm/lib/child/index.js:47:3)
at emitTwo (events.js:106:13)
at process.emit (events.js:191:7)
at process.nextTick (internal/child_process.js:744:12)
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)
So how can I test my component if the nested component is connected to Redux? O_O'
Update:
I was importing the history from react-router from my main app file, index.js, and called it to push a new route inside one of my OtherComponent methods. It seems that was what caused the issue. So I guess I should not be using history inside my components? How would I handle that in my test if I chose to keep it that way?
import { history } from '../'; // index.js file with ReactDOM injection
class OtherComponent extends Component {
// ...
someMethod() {
callSomeActionCreator();
history.push('/some/route');
}
}
回答1:
One way in unit test is to focus only on the actual component and only test its behaviour. To do so you have to mock out the all other dependencies. In your case you can mock out OtherComponent and then just test that it eas used with the correct parameters.
import React from 'react';
import { shallow } from 'enzyme';
import { MyComponent } from '../../components/MyComponent';
jest.mock('../../OtherComponent', () => 'OtherComponent')//note that the path is relative to your test files
This will replace OtherComponent with a simple component with name OtherComponent.
回答2:
Just to clarify, the Invariant Violation error isn't unique to testing with react-redux. Rather, the test suite fails when it isn't provided with a way to mount onto the DOM (much for the same reason ReactDOM would fail if you attempted to call .render on an element that isn't in the DOM).
Echoing off what @Andreas said - you can use jest.mock to initialize ReactDOM during the test's setup. Then, for react-redux specifically, you can pass the store to a tested component as a prop:
import Timer from './Timer';
import { store } from './store';
jest.mock("./index.js", () => "root");
describe('Timer test: ', () => {
it('should render', () => {
const wrapper = <Timer store={store} />
expect(wrapper);
});
});
With regard to your update: React Router provides a good example of how to test navigation-related aspects of your App here. The additional parameters you can provide to jest.mock may come in handy as well.
来源:https://stackoverflow.com/questions/42281607/react-jest-testing-nested-component-connected-to-redux-gives-invariant-violat