Skip to content

Instantly share code, notes, and snippets.

@fokusferit
Last active June 18, 2024 11:27
Show Gist options
  • Save fokusferit/e4558d384e4e9cab95d04e5f35d4f913 to your computer and use it in GitHub Desktop.
Save fokusferit/e4558d384e4e9cab95d04e5f35d4f913 to your computer and use it in GitHub Desktop.
Difference between Shallow, Mount and render of Enzyme

Shallow

Real unit test (isolation, no children render)

Simple shallow

Calls:

  • constructor
  • render

Shallow + setProps

Calls:

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render

Shallow + unmount

Calls:

  • componentWillUnmount

Mount

The only way to test componentDidMount and componentDidUpdate. Full rendering including child components. Requires a DOM (jsdom, domino). More constly in execution time. If react is included before JSDOM, it can require some tricks:

require('fbjs/lib/ExecutionEnvironment').canUseDOM = true;

Simple mount

Calls:

  • constructor
  • render
  • componentDidMount

Mount + setProps

Calls:

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

Mount + unmount

Calls:

  • componentWillUnmount

Render

only calls render but renders all children.

So my rule of thumbs is:

  • Always begin with shallow
  • If componentDidMount or componentDidUpdate should be tested, use mount
  • If you want to test component lifecycle and children behavior, use mount
  • If you want to test children rendering with less overhead than mount and you are not interested in lifecycle methods, use render

There seems to be a very tiny use case for render. I like it because it seems snappier than requiring jsdom but as @ljharb said, we cannot really test React internals with this.

I wonder if it would be possible to emulate lifecycle methods with the render method just like shallow ? I would really appreciate if you could give me the use cases you have for render internally or what use cases you have seen in the wild.

I'm also curious to know why shallow does not call componentDidUpdate.

Kudos goes to enzymejs/enzyme#465 (comment) this gist is basically a copy of the comment but I wanted to separate it from there as it includes a lot of general Enzyme information which is missing in the docs.

@OzzyTheGiant
Copy link

@ycjcl868
TL;DR:
Shallow: create and test component only (no children)
Mount: same as shallow but mounts with children and parent/host component, allows lifecycle methods
Render: outputs the html given by the component, including children

For those of you coming or familiar with Angular testing, Shallow is basically just testing the component while providing 'stub' children component in the TestingModule, if necessary. Mount would be the same but instead providing the real children components in the TestingModule. Render would be basically using the fixture.debugElement.query(By.css("") feature.

@fokusferit
Copy link
Author

Sorry everyone, this gist is still creating value for people, so I will allocate time this week, to get it updated for v3 of Enzyme. Especially as of React 15 (I think) many lifecycle methods are deprecated, so shallow and mount definitely behave different.

@yuliangjin1985
Copy link

Helpful. Just started to work on react and enzyme.

@LBWright
Copy link

@fokusferit as of Enzyme v3, Shallow supports CDM and CDU. I see your comment above, I do think it's worth mentioning, however.

@DKNY1201
Copy link

Good to know. Please keep it up to date. Thank you.

@misingnoglic
Copy link

Thank you!

@cythilya
Copy link

cythilya commented May 2, 2019

Thanks for sharing!

@kleva-j
Copy link

kleva-j commented May 4, 2019

Really helpful. Thanks

@Seolhun
Copy link

Seolhun commented May 8, 2019

Really good Things. Thanks.

@ChetnaGupta
Copy link

Concise and helpful! Thanks

@droidada
Copy link

I'm going to have this framed on my office wall 😆 thanks 👍

@BenjaminWFox-Lumedic
Copy link

If you're still maintaining this it would be useful to scope this to a specific version of enzyme or else update for latest version. I spent a little bit of time being confused about my test functionality before I realized that as of v3, shallow calls additional lifecycle methods.

@marin-k-marinov
Copy link

marin-k-marinov commented Aug 7, 2019

I have a question about testing a HOC component defined with withNavigation

class Device extends React.Component { ... }
export default withNavigation(Device)

When i try to shallow render it produces the following snapshot

<ContextConsumer>
  <Component />
</ContextConsumer>

I am not interested in testing the lifecycle of the component or behavior of componentDidMount, just want the snapshot to include the general structure and styling of the original <Device> component

@lukap2211
Copy link

@marin-k-marinov sounds like you just need render

@Dengyy
Copy link

Dengyy commented Sep 29, 2019

Great,and hope the api docs can explain more

@HarishSha
Copy link

Awesome 👍

@NauhcNoohc
Copy link

Thanks. Good thing for sharing👍

@kumarRaj
Copy link

kumarRaj commented Feb 5, 2020

Thanks 👍

@BernardoMG
Copy link

Awesome! Thanks 👏

@nok91
Copy link

nok91 commented Jun 23, 2020

Simple and neat explanation! Love it, Thank you!! 👍🏻

@akm
Copy link

akm commented Jul 4, 2020

Great! Thanks 👍

@loopser123
Copy link

thank u

@Snouzy
Copy link

Snouzy commented Aug 30, 2020

Thanks a lot 👍

@felipe2g
Copy link

Thanks!!!!!!!!!!

@catalinberta
Copy link

Good one

@CodingInvoker
Copy link

In enzyme V3 I think shallow can call React lifecycle methods as well.

See doc: https://enzymejs.github.io/enzyme/docs/api/shallow.html

As of Enzyme v3, the shallow API does call React lifecycle methods such as componentDidMount and componentDidUpdate

@mageshk98
Copy link

Simple and clear explanation. Thanks, @fokusferit.

@m-sakthi
Copy link

Good one.. Thanks.

@xinbbbb
Copy link

xinbbbb commented Aug 16, 2021

Thanks! 👍

@hut8
Copy link

hut8 commented Feb 13, 2022

@fokusferit Thanks for this!
One thing to improve with respect to use cases for each: What if you have a component that needs a context, like:

  • a component that must be wrapped in a provider, e.g., your SessionContext.Provider
  • a component that needs to be rendered inside of a router (MemoryRouter?) because it uses useLocation()

If you use shallow, won't it just end up "rendering" the SessionContext.Provider/MemoryRouter because that's the first level of component? That seems like it would always be useless. I'm trying to figure this out now, and Google sent me here, but your gist doesn't quite mention these cases. Thanks again 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment