Mocking an API call method inside componentDidMount

Viewed 72

Has anyone got any advice on how to unit test this component? I'm struggling to work out how to mock getFoo correctly and then wait for its promise to resolve before running my tests. I'm currently using Jest to try and do this.

import { getFoo } from "../../../api/fooApi";

class Accordion extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isActive: false,
      isLoaded: false
    };
  }

  componentDidMount() {
    getFoo(this.props.id).then(
      result => {
        this.setState({
          isLoaded: true,
          foo: result
        });
      },
      error => {
        this.setState({
          isLoaded: true,
          error
        });
      }
    );
  }

  render() {
    const { isActive, isLoaded, foo } = this.state;

    if (!isLoaded) return <Spinner />;

    return (
      <Accordion styled>
        <Accordion.Title
          active={isActive}
          onClick={() => {
            this.setState({ isActive: !isActive });
          }}
        >
          <Icon name="dropdown" />
          {foo}
        </Accordion.Title>
        <Accordion.Content active={isActive}>
          {foo}
        </Accordion.Content>
      </Accordion>
    );
  }
}

This is the actual method.

export async function getFoo(id) {
  const res = await fetch(`/api/foo/${id}`);
  if (res.status !== 200) throw Error;
  return res.json();
}
1 Answers

I would use nock, it lets you simulate an API response, here's a post detailing how to use it, it would be something similar to this:

...
import nock from 'nock'; 

it('renders without crashing', () => { 

   const scope = nock('http://myapi.com') 
   .get('/api/foo/')
   .reply(200, { products: [{ id: 1, name: 'nocked data' }] }, 
   { 
     'Access-Control-Allow-Origin': '*', 
     'Content-type': 'application/json' 
   }); 

   const div = document.createElement('div');
   ReactDOM.render(<ProductsList />, div);
   ReactDOM.unmountComponentAtNode(div); 
});
Related