Mock isolated service in a React Application
Tags: react, javascript, tutorial, beginners
Published: 2022-01-25 01:37:18

The term division to conquer was used throughout history in political and political ideals, consisting of the fragmentation of powers, thus, it is a strategy that aims to break or accompany between social structures and take them independently.

> "Divide and Conquer. - Júlio César"

Hi guys, how are you today? 
 
Based on the divide and conquer principle, i am writing this post to demonstrate how it is possible to isolate services in a react application and test them independently.

Step one: **Understanding the structure**

![structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rkdvvmsizhhd9pkq78e.png)

**Adapters** work as a bridge to the outside world, this is done through external functions or developed interfaces.

**Services** are a similar construct used by the repository pattern often used by the backend to build a superficial and literal layer between code and database.

**Entities** are interfaces and literal representations of the members of our application.


Step two: **Building an adapter**

```
import axios from "axios";

const api = axios.create({
  baseURL: process.env.API_BASE,
});

export default api;

```

> <center>/adapters/api.ts</center>


The code above is very simple, we are just creating a new instance of axios and exporting it to the rest of the application.

Third step: **Assembling the entity**

The entity is just a type with its respective attributes.

```
export type TUser = {
  name: string;
  email: string;
};
```

> <center>/entities/user.ts</center>


Last step: **Finally the services**

```
export const registerUser = (user: TUser) => {
  return api.post("api/user", user);
}

export const getUser = (id: number) => {
  return api.get(`api/user/${id}`, user);
}
```

> <center>/services/user.ts</center>


> Ui

Our ui is composed of two inputs and a button with their respective data-testid

```
<Input data-testid="inputName" />
<Input data-testid="inputEmail" />
<Button data-testid="submit" type="submit">Save</Button>
```

> Writing the tests

First let's mock the service

```
import * as user from "/services/user.ts";

jest.spyOn(user, "registerUser").mockImplementation(() =>
   Promise.resolve({
      message: "created"
   })
);
```

The magic is in the code above, we are exporting the entire service file and telling spyOn to look at it as a function object

```
it("Must submit a new user", async () => {
  const { getAllByTestId } = render(<User />);

  const name = getAllByTestId("inputName")[0] as   HTMLInputElement;
  const email = getAllByTestId("inputEmail")[0] as HTMLInputElement;
  const submit = getAllByTestId("submit");

  fireEvent.change(email, { target: { value: "email@email.com" } });
  fireEvent.change(name, { target: { value: "Miguel" } });
  fireEvent.submit(submit);
  await waitFor(() => 
        expect(user.registerUser).toHaveBeenCalledTimes(1));
  });
```

In this case we expect our form to call our registration function at least once.

And we reached the end of the tests, the big point is in the import of the service that will be a mock. Take a good look at how the spy function works.

![Naruto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/068j7du3ioxra0e5os4v.gif)

<center>Time is very important, thanks for sharing a little bit of yours with me 😊.</center>

<a style="float: left;" href="https://github.com/devneto">![image](https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white)</a>