Skip to content

Instantly share code, notes, and snippets.

@indiesquidge

indiesquidge/App.js

Created Oct 6, 2017
Embed
What would you like to do?
Mocking modules in Jest
export default {
fetchUser: () => fetch(`https://api.github.com/users/mlimberg`).then(res => res.json())
}
import React, { Component } from 'react'
import api from './api'
class App extends Component {
constructor () {
super()
this.state = {
name: null,
imgUrl: null
}
}
async componentDidMount () {
// here we use a local `api` module to make our fetch
// requests, rather than using the `fetch` global.
const userJSON = await api.fetchUser()
this.setState({
name: userJSON.name,
imgUrl: userJSON.avatar_url
})
}
render() {
return this.state.name ? (
<div>
<img src={this.state.imgUrl} alt="github avatar" height="100px" />
<h1>{this.state.name}</h1>
</div>
) : (
<div>Loading…</div>
)
}
}
import React from 'react';
import App from './App';
import { configure, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
// http://airbnb.io/enzyme/docs/installation/index.html
configure({ adapter: new Adapter() })
// This is how we override modules that our source code uses and mock them out
// in our tests. In this case, our source code imports `./api.js`, so we need to
// create a mock object to take its place within `./__mocks__/api.js`.
jest.mock('./api')
it('displays the GitHub username and avatar image', async () => {
const wrapper = mount(<App />)
expect(wrapper.state()).toEqual({
name: null,
imgUrl: null
})
// since we are calling `fetch` directly in `componentDidMount`, we need to
// wait for that lifecycle to finish before we can assert against the wrapper.
await wrapper.instance().componentDidMount()
expect(wrapper.state()).toEqual({
name: 'GitHub name',
imgUrl: 'GitHub avatar_url'
})
})
// GitHub gists won't allow subdirectories, but this file would exist in a
// `__mocks__` folder that is a sibling of the module we are looking to mock.
//
// src
// ├── __mocks__
// │   └── api.js <-- this file
// └── api.js
//
// Notice the similarities between this exported object and our actual `api`
// object. Both files export an object with a `fetchUser` property on it that
// returns a promise.
//
// It is easier in our test file to see that something is being mocked because
// of the explicit `jest.mock` function call.
//
// This pattern is also extensible. If we had another component that made use of
// another api method, say, `fetchRepos`, then we could mock that same property
// on this object here with whatever return value we wanted to expect in our test.
export default {
fetchUser: () => Promise.resolve({
name: 'GitHub name',
imgUrl: 'GitHub avatar_url'
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.