Question: Getting into functional components + hooks and React Unit testing, I'm trying to do the following:

In one compnent, I use a function from a utility API file. On mount, Im making an async function call to my api.
In that utility API file, I want to mock the function various ways so when I render my component in the test, it will see different responses in the hooks. It will return a Promise that will resolve to different values based on what I'm testing.

So I'm not mocking third party modules, Im mocking my own modules.

```js
/**
 * App.js
 */
import React, { useState, useEffect } from 'react'
import { getData } from './api'

export default function App() {
  const [data, setData] = useState()

  // get data from api on mount
  useEffect(() => {
    loadData()
  }, [])

  // get the data and set the "data" state variable
  const loadData = async () => {
    try {
      let d = await getData()  // <---- this is what i want to mock with different values per test
      setData(d)
    } catch (err) {
      setErr('Error occurred')
    }
  }

  render (
    <div>
      data is: {JSON.stringify(data)}
    </div>
  )
}

```

Just looking for a way to define the mock in my test file per test, so when my component is rendered it will resolve/reject to different values

Answer: 
You can mock your getData function from the api as follows:

```js
import {render, wait} from 'react-testing-library';
import {getData} from 'path/to/api';

jest.mock('path/to/api', () => ({
    getData: jest.fn()
}))

it('succeeds when promise resolves', () => {
  // This overrides getData with a resolved promise
  getData.mockResolvedValue('foo');

  const { container } = render(<App />);
  // You need to wait for your mock promise to resolve
  return wait(() => {
    expect(container.textContent).toBe('data is: "foo"');
  });
});

it('fails when promise rejects', () => {
  // This overrides getData with a rejected promise
  getData.mockRejectedValue('oh no');

  const { container } = render(<App />);
  return wait(() => {
    expect(container.textContent).toBe('Error occurred');
  });
});

```

What this basically does is that when your api is imported it returns the dictionary returned by the mock factory.

You can mock the module with `jest.mock`, and then override the function to resolve/reject to different values in each test.
Daniel's answer explains a good method for mocking modules. Another way to mock `getData` is with dependency injection.

```js
import {getData} from './api';

export default function App(props) {
  const [data, setData] = useState()

  // get data from api on mount
  useEffect(() => {
    loadData()
  }, [])

  // get the data and set the "data" state variable
  const loadData = async () => {
    try {
      let d = await props.getData() // <-- change this to props.getData()
      setData(d)
    } catch (err) {
      setErr('Error occurred')
    }
  }
}

App.defaultProps = { getData };

```

By setting the "real" `getData` as the default prop, your app will call the "real" getData from './api' when you render `<App />` with no props.

However, in tests, you can now pass in a mock `getData`:

```js
it('succeeds when promise resolves', () => {
  const mockGetData = jest.fn().mockResolvedValue('foo');

  const { container } = render(<App getData={mockGetData} />);
  // You need to wait for your mock promise to resolve
  return wait(() => {
    expect(container.textContent).toBe('data is: "foo"');
  });
});

it('fails when promise rejects', () => {
  const mockGetData = jest.fn().mockRejectedValue('oh no');

  const { container } = render(<App getData={mockGetData} />);
  return wait(() => {
    expect(container.textContent).toBe('Error occurred');
  });
});

```