Components — the same and the different Tests should help me be confident that my application is working and there are better ways to do that than shallow rendering. This was written not by me, but by , in his resent article, which was named more or less, but absolutely opposite to this one. Kent C. Dodds _Tests should help me be confident that my application is working and there are better ways to do that than shallow…_blog.kentcdodds.com Why I Never Use Shallow Rendering Let me highlight few moments ”why to use shallow”, Kent collected, and then ! Ie reasons to shallow rendering. myth-busted false … for calling methods in React components … it seems like a waste to render all of the children of each component under test, for every test, hundreds/thousands of times… For actual unit testing. Testing composed components introduces new dependencies that might trigger an error while the unit itself might still work as intended. He “myth-busted” all of the points, proving to all of us, that we shall never use shallow rendering for testing our components. It’s not reliable, not testing anything, and just doesn’t worth time spent on it. Let me do the same(myth-bust), but for mount. Let me strike back. Why I Never Use Mount Rendering The first reason — it’s slow. Not actually “just” slow, but “unpredictable” slow. renders just everything. There is no limits. When you want to test your small component – you will test a bit more than you may expect, and spent much more time than you expect. But this is not the issue, 1000 tests still could be executed in 10 seconds. mount The second — it could work today. But tomorrow, then you will made some changes to the underlying component — it will broke. And you cannot predict who, why and when will made that change. And who will have to fix it. The third — it does not work. Really — I could not get the point why anybody “should prefer over , while . mount shallow” **mount** does not work Mount does NOT WORK. As long it does TOO MUCH WORK. Really — renders everything from “here” and to the very end. Including all the nested Components and calling all the lifecycle methods of those components, making lots of side effects, you placed inside lifecycle methods, just because of “Component Approach”, of course. Side effects, you may not be aware of, or you just don’t want to execute. Or can’t. Or should’t execute in a testing environment. mount Some side effects could NOT be mitigated even with mocking. This moment is usually explained in articles about mocking, in short — don’t mock not dirrect dependencies. In another words — as long you are not controlling nested Components, you gonna render in mount, you are not able mock out the “bad Components”. They are not bad — they are nested. And everybody could just deeply refactor them. For example deeply nested component is fetching some information, loading third party script and so on. For example – Facebook Like button. You could not mock it – that not dependency of a component you are testing. Don’t mock, and honestly don’t test, stuff you are not in charge of. If your component is a bit bigger than nothing, has some Redux, Ajax, any other stuff — then probably you . Just could not. anywhere inside could not use mount Shallow rendering is the only way to run only the code, you have intentions to run. Only “subject under test”. But you might not have side effects, I am talking about. Side effects are not the main issue for . The main issue lays in another dimension — mount renders component, as it will be rendered in real. In all the details possible. mount For some of you this is the reason why you should use mount, but for me – opposite. I am afraid of the real realty. Too real for me. Let’s imagine you have Tooltip element, and you are passing content inside using standard “ interface”. children import Tooltip from 'react-cool-tooltip'; const MyComponent = () => {<Tooltip><div>something: {veryImportantYouHaveToTest}</div></Tooltip>} Now test it. It is not as simple as it look like. Lets face the truth — it is, yet again — . So small and simple component, but you can’t test it. At least I can’t. You don’t believe? Let me elaborate more: impossible Tooltip will anything, unless someone , only then it will display children. “Clicking on it” is a part of a public interface, a “contract”, but do you see anything here, you can click on? That’s internal realization of Tooltip. There is no information how to “use” it. not render clicks on it You probably could just open Tooltip sources, and find the way to match a button inside. Probably it’s just button inside. Or should you pick it by class name, or A11n role? Or match by text as proposes in his ? But are you controlling that text? What if in the future library author will decide to make “that button” more fancy? Kent C. Dodds react-testing-library You can’t get the answer to these question, cos they are a subject to change. Tooltip could change internal realisation, as long as it is a third party library you are not controlling. And it will break all the tests. Accidentally. This is something “you shall no do”, and is explained in every second test-related book. And the best precipices are quite simple: . Simple? And you have agreed to it, as long you are not testing how CPU, HardDrive, or Browser works. That is not your stuff, and you don’t care. requirement of isolation And I am not sure why “react” unit testing should differ from “js”, “java”, and ”just code” best testing principles. Look like they should not. test only your stuff But I could just access props.children and test MY stuff! Yeah! No more talks, lets just solve the problem! expect(wrapper.find(Tooltip).props().children).toBe(something) But it will give you “raw” elements, you can’t assert. You have to intermediate render results, wrap with some usable helpers, and then assert: mount expect(mount(wrapper.find(Tooltip).props().children)).toBe(value) So – now you could assert, that you passed right props down to Tooltip, but it sounds like – you don’t have to “parent” element, only . mount chidren You also could Tooltip, and make it always just render children. Replace smart Tooltip but dumb component. But it sounds like – you don’t need — will do it better. mock mount shallow Why I Always Use Shallow Rendering There is only one reason – I am able to test the I could test. And that is limited to my current local “scope”. Usually – the single component. stuff stuff Shallow just records calls to React.createElement but never _creates_ any element. That’s why it does not render ANYTHING else. If I want to render nested component in real – I should explicitly say it – . Without dive – Tooltip is a “tag”, not a component, but just a record in memory. Deep diving could fight for the good, and could be the bad. know more about it, and how deep diving could save the day: wrapper.find(Tooltip).dive() Kumar McMillan _When the Firefox Add-ons team ported addons.mozilla.org to a single page app backed by an API, they chose React and…_hacks.mozilla.org Testing Strategies for React and Redux - Mozilla Hacks - the Web developer blog This article clearly, may be much more clearly than this one, explains why you often have to use shallow, and how to escape from shallow design limitations. And next I will explain the main point of the whole article What does shallow or mount tests actually tests? May be they test components? Do you have another tests, which tests not components, but “code”, or “application”? I could name just a few: Smoke tests, unit tests, integration tests, end-2-end tests, PDV tests… Unit tests stands for putting small functions and small components into specific , and testing that everything works as predicted. situations E2E tests stands for testing actual work. browser PDV — the same as E2E but only with real . environment Integration tests (and E2E) are testing how application is . WIRED Every type of tests are testing somehow better than another, testing the stuff from different prospective, giving different confidence, different not in quantity or quality, but in different of confidence. colour Mount is good for unit and integration testing, could check the “wiring” of the App. But Cypress could do it even better. What about Storybook storyshots? And the question you have to answer is following: What testing could provide for you? ? That shallow can do, mount cannot? May be not better, but from another angle? shallow What it does better ….. Shallow Tests are Structural Tests. Shallow not letting you test how your component will work, but let you to test how it was assembled. If you think you have assembled correctly, and tested it – then you have tested all the stuff you should test. If then code doesn’t work in “real” – then or your assertion was not quite correct, or your , other pieces of code, not the current-component-under-test, . That’s their fault, not yours. It’s a goal of unit testing — spot a real place of a problem, not just spot the problem. component composition peers are broken Shallow is a way to test component composition. In my expirence shallow tests are everything you need. Mount will not give as much confidence as Cypress-i-will-test-a whole-app could do, and even could require MUCH more effort. As I said — tests a different. As result — the maximal confidence is a result of a test composition, or testing pyramid: tests small pieces. . Unit Atoms tests small pieces combination. . Shallow Molecules tests result as a whole. . Cypress Organism When shallow sucks. Yeah — I just said that shallow sucks. First because of the way it works – for example it’s absolutely with . Second – enzyme, by its own, not compatible with React 16 stuff, including Context API, now used everywhere. incompatible renderProps was Now enzyme is fixed, and look like will never “broke” again. Lets try to solve the problem with RenderProps As I mention above — shallow could see only commands, called in the current component. With renderProps code is hidden inside is not executed untill “parent componet” will “render” it. For shallow — it, and everything inside . React.createElement function-as-children it, does not exists You can into a Component made of RenderProps, but that it may require more than one dive, having in mind quite heavy usage of Context API nowadays. dive Second problem — not every dive into component will provide a result you are able to use. And long ContextAPI.Consumer, for example, could not have corresponding Context.Provider. Third problem — then you dive — you are leaving current location, and never knew where you will emerge again. In depends on realization of a component, you are diving into. And that could be not-controlled component. You are shallowing a virtual ReactTree, but diving into a Real one. And you are also loosing ability to “overview” all the stuff you are rendering, which actually distinguish shallow from mount. Mocking here will also NOT help you, as long mocking is mocking a realisation, and shallow doesn’t give a shit about realisation, only about composition. Mocking will help only if you dive into the component, but, just a few lines above I’ve said — diving is not for every case. That’s a design limitation we have to live with. Anyway — how to solve renderProp issue with shallow Simple! , even if I just said that you could not use mocks, even if I just said that mocking will not work. Feel free to use another version of mocking — not dependency mocking, but method overriding. Not , but . Just Mock component .mock .stub Lets pick almost school example — and almost school solution — just “unwrap” render prop You may automate this operation — just , and as you want. For example — instantly call all function-as-children, if you know how to call em. mock React.createElement createElement const createElement = jest.spyOn(React, "createElement"); createElement.mockImplementation(({type, props, children) => doWhatEverYouWant); get’s component type and children as input, and, actually, returning the same information it was given. That is an instruction to React, and that’s the only information shallow will work with. By controlling React.createElement . createElement you are controlling shallow rendering I’ve created a special library for this, capable to solve puzzles like this, and the others. I am not trying to solve the problem by brute force, but look at on from another angle. Could not use dependency mocking — don’t use it. Simple. _react-remock - Get any Component replaced. Anywhere. 🛠♻️_github.com theKashey/react-remock The second, and almost the same variant is to use enzyme-extension library _enzyme-extensions - 🎩 Enzyme extensions to test shallowly rendered enzyme wrappers 🏄🏻_github.com commercetools/enzyme-extensions There is a little difference how they work — here is a comparison: Well, when to use mount? Well, always, when you can. And the only problem — you don’t always CAN. But that is not a problem of , but the problem of the code you written. mount Hard to test code is hard to 😍 code. And the only way — make the code be more testable. For me it is the law of the universe — if you can’t do something, for example test — split that something into the smaller, “doable”, pieces. Divide and Conquer. A divide and conquer algorithm works by recursively breaking down a problem into two or more sub-problems of the same or related type, until these become simple enough to be solved directly. Dissolve one big component into the smaller ones, you can , then — test their . test using mount composition using shallow An example? const Application = () => (<ThemeProviders><TopMenu /><Routes /> <-- contains side effect. could not test<BottomMenu /></ThemeProviders>) /////////////////////////////////////////////// // now - testable by mountconst ApplicationChrome = ({children}) => (<ThemeProviders><TopMenu />{children} <--- MAY not contain anything<BottomMenu /></ThemeProviders>) // now - testable by shallowconst Application = () => (<ApplicationChrome> <--- testable by mount<Routes> <--- "untestable" routes are injected in the container</ApplicationChrome>) It’s more about DI(D in SOLI ), the Dependency Injection pattern, when you can create your Application without internals, without blocks containing side-effects, preventing a whole Component from being tested. And then inject those internals. This is something is talking about in his , but from a testing point of view. D Dan Abramov props drilling twitts Just try to apply best practices from “normal programing” to “react programing”. Split big components into the smaller and testable ones. This is like Container/Component separation in Redux, everybody is aware of, just without Redux. This is something about DRY. I would not say that splitting React components, as thus making more and more components is a good idea from . It is not. Be pragmatic, and maintain ballance. This is not a silver bullet you can always use !! performance point of view !! I would not say that splitting is even possible with renderProps, as long it’s super common, when code inside function-as-children uses variables from the parent scope. If you will move function off the component — you will have to change call signature, to “take variables with you”. But problems like this were solved for “function composition”, and not a problems — they are just requiring a bit different code taste. const MyComponent = (props) => {<Context.Consumer>{ (contextValue) => ( <--- not "easy" testable by shallow<div>{props.value} 😍 {contextValue} <AndSideEffect /></div>)}</Context.Consumer>} /////////////////////////////////////////////////// // testable as using shallow// interface is still "component-compatible"const RendedProp = (props, contextValue) => (<div>{props.value} 😍 {contextValue} <AndSideEffect /></div>) // just move MyComponent to another file, and you will able// to "mock" RendedProp using jest.mock // now testable by mount.const MyComponent = (props) => {<Context.Consumer>{(contextValue) => RendedProp(props, contextValue)}// or{(contextValue) =><RendedProp props={props} contextValue={contextValue} />}</Context.Consumer>} Hint: In the last example I’ve used as , in ComponentCase convention, but called it as a function. You probable saw this trick before, and some one even proposes, that it speed ups whole rendering. renderProp RenderProp Calling SFC as a functions is something React does underneath. You are just taking it’s job, and “inlining” “components” instead of “creating” them. That is the different? Actually, internals of components, rendered this way, are visible to shallow 😉. Yet another power tool to amend shallow testing, but please don’t overuse it. Side note about splitting components Proper splitting could save the day. Extracting all the side-effects you may have inside Components to the route level, using redux-first-router, could make tests easier. Splitting Components and Containers — makes both components MUCH more testable, than their union. Sometimes you don’t need a better tool, to better do something. You need another point of view. Another approach. Keep this in your mind. Conclusion As the conclusion — I would say — only a Sith deals in absolutes. is a tool, is tool, . Other tools and testing from another angles and another dimensions — completes each other. Mount shallow they completes each other I am using Enzyme, React-test-renderer, Cypress, Nightwatch, Jest, Sinon, Mocha, Snapshots, Screenshots, and maintaining some huge projects without a single test. I am using different approaches to test my libraries, my components, my applications, and combinations of applications. Just try to find out that is better for you, and for you team. Don’t just say — never use shallow. Never say never. Divide and Conquer.