-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Testing a Redux-connected component using Enzyme #1002
Comments
const wrapper = shallow(<ConnectedComponent />).dive(); and then make your assertions on the wrapped component. |
Any update to this? I secondly this very strongly. Everything I have tried does not work. I set the context like shown in the docs -- http://airbnb.io/enzyme/docs/api/ReactWrapper/setContext.html This also looked promising But usually everything leads me back to:
😢 |
There's no update needed; wrap your connected component and use .dive(). |
Two things:
I still get the same ole error:
I get
when my test tries to use the API method I am assuming it cannot find it, because it is trying to find an grandchild element of my DatePicker component. |
I'd generally recommend using only shallow as much as possible, and only making assertions on which components your thing renders - in other words, if A renders B which renders C, your A tests shouldn't know anything about C, and should only be asserting that A renders B with the right props. Your B tests should be asserting things about C. |
Right. Makes sense. What I am trying to do is more of an integration test. I am sort of new to making tests. Would this thinking be more correct: If my For my test, rather than simulating that click event. I should be directly testing my (I apologize if this got off scope a little bit, just trying to understand). |
Yes, you definitely should be unit-testing your onDateChange. It's your date picker component's tests' job to ensure that onDateChange is called at the proper time. |
thank you, this has been very helpful |
@ljharb Is there any way to mock the inner component? Instead of shallow/dive. |
@shakiba Mocks make tests more brittle; but shallow rendering is kind of like automocking. Can you elaborate on what you're trying to achieve? |
@ljharb The reason that shallow does not work for me is that there are other nested components which I want to be rendered, such as bootstrap-react layout components. Basically instead of including specific components in rendering using dive, I want to exclude few components from being rendered. I solved it using |
enzyme v3 and React 16 will provide an API for that; short of that, that's probably the best option. |
Maybe it will be helpful for someone: If you want to find if connected component is rendered you can find it by Example (StylePicker is connected with the store): index.js
index.test.js
|
@przemuh better would be |
@ljharb regarding the question in #1002 (comment), don't we still need to use something like |
@mstorus correct, it won't affect that. |
sometimes you might have to double dive ( For example lets say you're wrapping your connected container in another wrapper like this, you'll possibly have to double dive I've found because you need to now get past the ReactTimeout HOC and dive to get past the react-redux connect wrapper HOC in order to work with the container.
|
Totally correct - you need one |
Is there any syntactic sugar available for components wrapped with react-router's Instead of a test like:
|
@michaelBenin |
If you don't need access to the redux store as part of your unit test, don't forget that you can also export the React component individually in addition to exporting the connected variant by default. export class Component extends React.Component {}
export default connect(({ someReducer }) => ({
...
}))(Component) In your test, just extract the "pure" Component rather than the connected one: import { mount } from 'enzyme'
import { Component } from '../components/Component'
...
mount(<Component />) |
You shouldn't do that, however, because if it's never used by itself in production, there's no value in testing it by itself. Use |
I wouldn't say that it has no value @ljharb but I also know what you mean. Using renderComponent = (props = {}) => shallow(<Component {...props} />).dive()
const dispatchMock = jest.fn()
const component = renderComponent({ dispatch: dispatchMock })
component.find('form').simulate('submit')
expect(dispatchMock.mock.calls.length).toBe(1) |
@trevorwhealy that's worth exploring - i don't see any |
@ljharb sure we can agree on that. updated the code to reflect the implementation more closely. |
Referencing @gecko25's comment above - I get that same error...
The connected component has some internal state that I want to test. |
What happens if there are multiple children of the component, one of which is connected?
In that case I can get around this by doing
but that makes for a really fragile test. I suppose in that situation I can do what was suggested above:
but I'm curious if there's a better solution. |
Redux's connect creates a new higher-order component wrapping the component you want. So dive accessed the one child of the Redux wrapper, which is the actual component you're looking for. |
had a similar issue. with dive() I get such an error: |
you may need to pass the context manually when using dive, pending a known issue |
Finally, I somehow made it work which may help someone. Just pass your store to your component like said above.
But after doing it so, I met an another error called,
After searching for other answers in SO, I found that, I was using createBrowserHistory throughout out my application, in store, whereas createMemoryHistory is more than enough to test unit test cases. All the test cases have been passed, after changing it so. Note: I am just new to Jest and correct me if it go wrong at any specific cases. |
Where did you get the store from? |
I too struggled with this one for a bit piecing together what I found on various related results. This is my working test: https://gist.github.com/ncpope/a9da1698d919108f104cd1d7e4bec5e9 I am additionally using Redux Mock Store to achieve these results. |
how do i use shallow with mount. i am trying to do this |
I have written the helper which I use once I need the redux connected components to test. Here it is: import { Provider } from 'react-redux';
import { mount } from 'enzyme';
import configureMockStore from 'redux-mock-store';
const defaultStore = { responsive: { fakeWidth: 1200 } };
const mockedStore = configureMockStore()(defaultStore);
export const mountWithProvider = children => (store = mockedStore) =>
mount(<Provider store={store}>{children}</Provider>); Then you're able to use it as follows: const props = {};
const wrapper = mountWithProvider(<SomeConnectedComponent {...props} />)();
expect(wrapper.exists()).toBe(true); Also you can set custom state of the store to override the default one defined in the helper scope: const myCustomState = {
myName: 'test',
myAge: 9999
};
const wrapper = mountWithProvider(<SomeConnectedComponent {...props} />)(myCustomState); |
@ljharb this works for me class Session extends React.Component {
...
render() {
<div>
...
<MealSessionModal propOne={propOne} />
...
<div>
}
}
const wrapper = mount(
<BrowserRouter>
<Sessions store={store} {...props} />
</BrowserRouter>
) but this was throwing th error const wrapper = shallow(<Sessions store={store} {...props} />).dive() which worked fine. My other question is, how could I use the mounted parent |
Thanks so much! Your solution solved most of my problems :D |
Has the first question been solved? I only saw you discussing mount and shallow,And I still report an error now. |
I had the same problem. This solution worked for me: |
The problem I have ai A is wrapped with |
This was super helpful. Thank you. |
Cool bro, now I can see the child props |
Omg, thank you! After hours of trying, this finally worked. <3 |
@trevorwhealy This worked, but what if I have inner components we I only export the
|
@KarinGarciaZ |
I am getting the same issue, I am using IntlProvider this is how I mount the component
the .dive() doesnt work with this, now I get this error |
@carolozar use the |
What if I don't want to test the redux because we are undergoing a process of normalizing our store and testing the connected components with a mock store makes our tests extremely brittle. We change the store and now we got tens if not hundreds of tests failing. To be clear, I'm just looking for a non hacky standard way of testing a non-connected component that has connected component children. |
@chase2981 if you use the component in your real app without the connection wrapper, then test it that way - if not, then it’s correct that hundreds of tests start failing when you change the store in a breaking way. That friction is a useful indicator that perhaps you should design APIs so they can evolve in non-breaking ways :-) |
I disagree. If we are changing redux and only redux, we haven’t even
touched the params or the components—it shouldn’t break all our component
tests. As a team we elected to move away from that approach for this very
reason. Unit tests are supposed to be done in a way to where they flex with
your code changes, and only break if the exact functionality you are trying
to test changes. In our case we were just trying to test components and
like pushing btns and inputting text and asserting it calls the onChange
callback and stuff like that. With the connected component tests, you can’t
even really assert on the dang action payload being emitted, and you damn
sure can’t mock some http call in an action that is being called somewhere.
Our development manager was even questioning whether tests were even worth
it in react to me after this latest episode.
So we’re moving to true unit tests now. To where they will only break if we
change the component—not the redux. The redux tests can break if we change
the redux.
However, the thing we still run into now is when we have a connected
component which we export the non connected component from for test
purposes, then we mount the non connected component—it still throws a fit
cuz one of its children is connected. I know you can do shallow but I swear
it still happens in that case, and shallow just isn’t the same. It doesn’t
knock out as much test coverage either. So just recently I started
resorting to mocking the inner container components using jest.mock and
instead having them return a div, which works and all, but say you relocate
some inner component dependency to a new folder somewhere, the ide doesn’t
pick up on the jest mock paths and therefore doesn’t know to update those
particular paths, so even that jest mock inner connected component approach
seems a little flaky.
Tbh coming from angular world where you have complete control over every
little thing in their unit tests, it just seems like react/react-redux
doesn’t really have their shit together in terms of true valuable unit
testing.
|
This guy recommends not even testing your container components and just structuring your app a little differently and testing everything else individually. https://link.medium.com/1Cd79oA3qab |
The exact functionality you should be trying to test is "how your component works" - the store connection is absolutely part of that. Proper unit testing does NOT just test "the code under test", it fully integration-tests the thing it's testing. |
I've tried all of these but same error
|
Enzyme
i) What is the least error-prone way to test a Redux-connected Componet using Enzyme?
I have checked many links and articles but haven't found a satisfactory answer. It's confusing me a lot.
ii)How can I test whether my component is getting certain props or not using Enzyme?
Versions
The text was updated successfully, but these errors were encountered: