> For the complete documentation index, see [llms.txt](https://sandeepamaranath.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sandeepamaranath.gitbook.io/notes/languages-and-frameworks/javascript-testing-jest.md).

# JavaScript Testing (JEST)

## What is Mocking?

{% embed url="<https://www.youtube.com/watch?ab_channel=Academind&t=21s&v=4Fl5GH4eYZ8>" %}
Mocking video
{% endembed %}

Let's say in our app, we need to call an API. `loadTitle` is a function that calls `fetchData` function. `fetchData` function is placed in `http.js` file. `fetchData` function then calls `axios` package and this `axios` has `.get` method that calls API and returns the data.&#x20;

`fetchData` function gets back that data and extracts the title in it and sends it back to it's caller who is `loadTitle`. `loadTitle` function converts this title into upper case (transformed text is sent back) and sends it back.&#x20;

![Nothing mocked yet](/files/s8tACN1kxDruiqBsrRLJ)

Now let's say we are writing a test to test if loadTitle() returns properly transformed upper case text. But when we test this, we need to call loadTitle which in turn calls fetchData which then calls axios.get() and makes an API request.&#x20;

For testing our loadTitle function we need to avoid somehow calling API. Let's step back and think what can be done. Let's answer this question, what if loadTitle gets the data from fetchData is not the data coming from the API! That's still Ok right as we don't care from where the data is coming back into loadTitle function. All we care about in the test is whether or not the loadTitle test is passing or not, meaning if loadTitle function is able to convert the data coming from fetchData to upper case or not.

So we have two options here.&#x20;

* We can either make fetchData function return a mocked data back to loadTitle instead of fetchData reaching axios
* The second option is to make axios.get() return the mocked data instead of axios.get() calling an API

### How to Mock

#### Mocking fetchData function

![Mocking the fetchData function call](/files/7FJY3DUcehwBS5UctPDt)

So in **option 1**, we mock the fetchData function placed inside http.js file. How to do that?

* Create a \_\_*mocks* \_\_ folder and add `http.js` file inside it. This is the file where the original fetchData function is exported.&#x20;
* Write a mocked function to return what you want
* Inside the test, place this code jest.mock('./http.js')&#x20;
* Now the mocked fetchData is called

#### Mocking axios package (basically mocking axios.get() function to be specific)

![Mocking axios(package's) get function ](/files/NSmwwSztKitwP3IItf54)

In **option 2,** we mock the axios.get function. How to do that?

* Inside the \_\_*mocks*\_\_  folder create the file with the package name you need to mock, axios.js in this case. So the file will be axios.js
* Write a function here called get() and export it. Make sure it returns a promise like below

![get() returns promise mock data - 1st way with Promise.resolve, no async keyword](/files/OFfMIC8Sx4DdBRdpKXgx)

You can also make this function async so that it returns a promise by default so that you don't have to use Promise.resolve but straight away return the object.

![get() returns a promise mock data - 2nd way with async keyword, no promise.resolve](/files/OSVgze1cCpHi690hv1tO)

* Now the test runs without jest.mock as, when it hits the axios package, it looks at mocks folder and automatically picks that up

#### Code&#x20;

![](/files/yK2iRBNdn1Xo1fAYKgPB)

{% code title="index.html" %}

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="styles.css">
    <title>JS Testing</title>
</head>

 <body>
    <section class="control-panel">
        <button id="btnAddUser" class="button">Add User</button>
    </section>
    <script src="dist/main.js"></script>
</body>

</html>
```

{% endcode %}

{% code title="app.js" %}

```javascript
const {printTitle} = require('./util')
const button = document.querySelector('button')

button.addEventListener('click',printTitle)

exports.printTitle = printTitles
```

{% endcode %}

{% code title="http.js" %}

```javascript
const axios = require('axios')
const fetchData = () => {
    console.log('This is coming from main fetched data')
    return axios.get('https://jsonplaceholder.typicode.com/todos/1')
            .then(response => {
                console.log('This is coming from main axios data')
                return response.data
            })
}

exports.fetchData = fetchData
```

{% endcode %}

{% code title="**mocks**/http.js" %}

```javascript
const fetchData = () => {
    // return axios.get('https://jsonplaceholder.typicode.com/todos/1')
    //         .then(response => response.data)

    // above is mocked
    console.log('This is coming from mocked fetched data')

    return Promise.resolve({
        title :'delectus aut autem'
    })
}

exports.fetchData = fetchData_httjs
```

{% endcode %}

{% code title="**mocks**/axios.js" %}

```javascript
const get = async(url) => {
    console.log('This is coming from mocked axios data')
    //  return Promise.resolve({data:{
    //      title:'delectus aut autem'
    //  }})
     return {data:{
        title:'delectus aut autem'
    }}
}

exports.get = get
```

{% endcode %}

{% code title="package.json" %}

```json
{
  "name": "js-testing-introduction",
  "version": "1.0.0",
  "description": "An introduction to JS testing",
  "main": "app.js",
  "scripts": {
    "start": "webpack app.js --mode development --watch",
    "test": "jest"
  },
  "keywords": [
    "js",
    "javascript",
    "testing",
    "jest",
    "unit",
    "tests",
    "integration",
    "tests",
    "e2e",
    "tests"
  ],
  "author": "Maximilian Schwarzmüller/ Academind GmbH",
  "license": "ISC",
  "devDependencies": {
    "jest": "^23.6.0",
    "webpack": "^4.20.2",
    "webpack-cli": "^3.1.2"
  },
  "dependencies": {
    "axios": "^0.18.0 "
  }
```

{% endcode %}

{% hint style="success" %}
I couldn't add this to my git repo as this is done on my office laptop and it takes more time to set git on this. Hence I've placed all the files above. If you want to see the project then go the my office mac here&#x20;

`/Users/samarnath/Documents/TestCode/js-testing-introduction`
{% endhint %}
