Potential issues with `store` as a prop and shallow test rendering in v6
See original GitHub issueI’ve seen a few different reports related to this topic, so I’m going to open up this issue for discussion.
In React-Redux v6, we removed the ability to pass the store as a prop named store
directly to connected components. (See my post explaining why this change was made.)
Generally, the only meaningful use case I knew of for this capability was for unit testing, as some people passed a store directly as a prop instead of wrapping the component in a <Provider>
.
I’ve seen some complaints that Enzyme’s shallow()
does not work well with putting a <Provider>
around a connected component, but I’m not clear on the details of what exactly breaks.
Is it that Enzyme still does not support React’s createContext
correctly? That rendering shallow(<Provider store={store}><ConnectedComponent /></Provider>)
does not actually generate any output from <ConnectedComponent />
? Something else?
As a related question, what exactly does it mean to “shallow-render a connected component”? What do tests with this approach look like, particularly in terms of Enzyme API usage and assertions?
I’d appreciate some examples of tests that are having issues, explanations of what specifically is breaking (beyond just “I can’t pass the store as a prop any more”), and any further details people can provide related to this issue.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:8
- Comments:78 (25 by maintainers)
Top GitHub Comments
One of the biggest problems I have with React and Redux lately is that they are slowly both forcing everyone down the path of using the Context API without considering backward compatibility for isolated tests specifically with the most popular lib used still which is enzyme. All along React’s and Redux’s API was simple enough to where you could do simple things with it through shallow. That’s no longer the case as this API evolves…and those who have happily and effectively written tests this way are having to come back and let you folks know about it when I think these uses cases should have already been found and part of React and Redux release testing.
By using the Context API that requires you to use mount() because you simply can no longer do easy things to components such as shallow. Redux 6 shut off the ability to pass in fake stores as props. All my past tests will break if we upgrade. Do I want my clients to sit on v5 for the next 5 years? I guess they could or we would have to rewrite the application (worse). Both situations are bad for the users of Redux and React in both scenarios; Wouldn’t it be better would be if React and Redux would allow us to continue to write isolated tests easily as we’ve been able to do for the past 3-4 years by not restricting the API or changing it in a way that would prevent test simplicity?
I personally don’t like using provider in my tests, it’s huge bloat. It’s been completely necessary the way I code react applications…unless you’re writing integration tests. That’s the thing, the React team seems to mainly just promote integration testing which is another beef I’ve had with that “framework”. I cannot call this a lib anymore.
What if there are those who don’t want to use contextAPI for persistence and actually are fine with passing state as props and find that route “simplistic” regardless of the “inconvenience”.
The problem I see is that the way React and Redux are moving, they’re continually changing the API in a way that undermines the ability to shallow and IMO they don’t really care because they would have already noticed that enzyme shallow is breaking due to their major API changes. They’re not backward compatible anymore, new react features are literally breaking things and they don’t care about isolated tests IMO generally which is my general take on it because if they did they’d already have seen this issue before releasing such major changes to their API.
It’s fundamental to be able to shallow components. That’s what made react and redux so great in the beginning. VueJS still has that ability in fact it’s built right into their testing lib.
On the point of TDD: I’m not saying you have to TDD. But those who do, we just want to be able to continue building these apps and test them in the same way we’ve always been able to. To shut off simple DI like that and to force people down paths that literally kill shallow to me is just not a very good move by React or Redux. The fact is if the React and Redux teams themselves wrote isolated tests more using enzyme shallow, they would have already seen this pain.
What if we’re not using createContext() and we still want to shallow test components and DI other ways through our isolated tests? Then we don’t use Redux anymore. Well that kinds sucks because if Redux 6 already allowed us to shallow easily and inject the store still, this wouldn’t even be an issue for those who test using shallow without provider.
But even after that, lets say we don’t use Redux anymore after that pain. React still is a barrier/concern because for example recently hooks, you can’t shallow render hooks. Another TDD’ist I know ranted on not being able to shallow render hooks. Sure we can put in an issue but shouldn’t the React team already figure that there are people who are going to want to shallow render still with “new stuff”?
I would like to think that at the least, the React and Redux team at least considers testing enzyme shallow and mount both, not just mount when they release stuff. They should find that hey, if we change the API this way, it might be good, but we might prevent the ability to shallow render with enzyme’s existing lib, something they’ve been able to do all along. Or they should say hey, if we remove the ability to inject stuff simply as props, it’s going to affect shallow tests in x way. The use cases are pretty simple on the enzyme side, you showed one already @markerikson
I don’t have time to write a huge blog post on this at the moment @markerikso. There are tons of articles that have been out there for years on shallow rendering React or Redux and passing in the store as a prop. Those are plenty of use cases IMO.
This issue has been partially superseded by the roadmap I just laid out in #1177 .
Key point: we’re going to switch
connect
back to using direct subscriptions internally, which means we can also bring back the use ofstore
as a prop, same as we had up through v5.I’ll leave this open for now, but basically this will get resolved when we actually figure out what the right internal re-mplementation of subscription logic is.