Mock API Call at FrontEnd
Tags: javascript, testing, react, apicall
Published: 2022-03-11 10:12:44


## Integration Testing
So when testing a component or page have you ever thought of if i can just check how would it behave if the data was coming from API.

**Question**: Why should you mock api
ans: you want to test the behaviour of the component and hardcoding data does not provide better test case.

Also backend and frontend can be develop in parallel and when any behaviour from the backend changes we can first test those changes if it breaks⛔️ anything.

Well worry not because if you are using Axios there is a pretty good library that can make the process smooth as butter on bread.
It is called **axios-mock-adapter**🔥.
 
For this blog i will be using React with jest and react-testing-library but we can use this library in any framework or just plain old vanilla JS. 


![jest Images with react](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xig4inxa34d9ms73mep.png)
Let's take a TDD approach and first make a test case for component where it fetch data from backend.

```
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
import data from './data';

//Component
import Products from "../Products";

const mock = new MockAdapter(axios);

// we need to reset after every test.
afterEach(() => {
  mock.reset();
});

// I keep all the mock data into separate file so 
// If there is any change we can just change in one file also 
// better for CRUD.
 
const MockData = data.Product

it("Mock Fetch Product Details", async () => {
  // mock fetch product details api
  // mock get  mock.onGet(URL) the URL should be exactly the same as the Axios request
  // we can reply with a positive response or a negative response using header Code

  mock.onGet("/api/products").reply(200, MockData);

  render(<Products />);

// wait for loading to complete
  waitForElementToBeRemoved(() => screen.queryAllByTestId("Loading"));

  expect(
    screen.getByText(MockData.description)
  ).toBeInTheDocument();

});
```
And that's it that was all for mocking api. 

![Mind blasting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sek2genr8cb9uezv1bvd.gif)

Now let's create component 

```
import axios from "axios";
import { useEffect, useState } from "react";

const Products = () => {
  const [products, setProducts] = useState<any>(null);
  const [loading, setLoading] = useState<any>(true);
  const [error, setError] = useState<any>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get("/api/products");
        setProducts(response.data);
        setError(null);
      } catch (error) {
        setError(error);
        setProducts(null);
      } finally {
        setLoading(false);
      }
    };
    fetchData();
  }, []);

  if (loading) return <div data-testid='loading'>Loading</div>;
  if (error) return <div>{error.message} </div>;
  if (!products) return null;
  return (
    <div>
      {products.map((product: any) => (
        <div key={product._id}>
          <h2>{product.name}</h2>
          <img src={product.image} alt={product.name} />
          <p>{product.description}</p>
          <p>{product.price}</p>
        </div>
      ))}
    </div>
  );
};
export default Products;

```

In next Test we will test fail response with 500 status code.
Note: we can check any response we want 
```
it("Mock Failed Response", async () => {
  const ErrorResponse = "Error Message"
  // we just need to change status code
  mock.onGet("/api/products").reply(500, ErrorResponse);

  render(<SingleProduct />);
  
  expect(
    screen.getByText(ErrorResponse)
  ).toBeInTheDocument();

});
```

If we want to test Post, PUT, DELETE we just need to change one line of code
`mock.onPost`
`mock.onPut`
`mock.onDelete`
or we can just put `mock.any` this mock any method request.

That was all but you the library can do much more than just this you also can cain api calls and create network errors.


```
mock.onGet("/api/products/product").networkError();

mock.onGet("/api/products/product").networkErrorOnce();

``` 
[Link to Repo](https://github.com/ctimmerm/axios-mock-adapter)

## Why should you mock the test

- frontend development can start with parallel to the backend.

- It's more better than just hardcoding the data into frontend for better reliability.

- The mock API can easily be replaced with the Real API once it’s ready and if any change in data happens we can test if it breaks anything.

- Error Handling — e.g., Timeouts, delays, validations, etc.

If you want to know more about testing you components i would recommend reading this article by kent c todds.
### [Blog Link](https://kentcdodds.com/blog/write-tests)

And that was all thanks for reading till now let me know how did you feel about the article, this is my first article or blog i would love to know you opinion.