Home > other >  How to test a function which has calls a another API function in it - NodeJS
How to test a function which has calls a another API function in it - NodeJS

Time:01-26

I have a function, which has another function in it. And in the second function we are making an API call. So how can I write a unit test for this scenario? I don't want to make an actual API call, I want to mock it.

 const getData = async (data) => {
    const res = await got.post(url,{
        json: {data}
    });
 
    const data = res.data;
    return data;
 }

function firstFunction(args) {
    // perform some operation with args and it's stored in variable output.
    let output = args;

    let oo = getData(args);
console.log(oo)
}

CodePudding user response:

When running unit test you don't have to call real API calls. You have to encapsulate your component and provide any external information.

With jest you can mock the http call and return what you want. And also you can check if the mock has been called.

import { got } from "anyplace/got";
import { firstFunction } from "anyplace2";

jest.mock("anyplace/got", () => ({
 // here you provide a mock to any file that imports got to make http calls
 got: {
   // "mockResolvedValue" tells jest to return a promise resolved 
   // with the value provided inside. In this case {data: 'what you 
   // want here'}
   post: jest.fn().mockResolvedValue({data: 'what you want here'});
 }
}));

describe('My test', () => {
 beforeEach(() => {
  // This will clear all calls to your mocks. So for every test you will 
  // have your mocks reset to zero calls
  jest.clearAllMocks();
 });

 it('Should call the API call successfully', () => {
  // execute the real method
  firstFunction({arg: 1});

  // check that the API has been called 1 time
  expect(got.post).toHaveBeenCalledTimes(1);
  expect(got.post).toHaveBeenCalledwith("myurlhere", {data: {arg: 1}});
 })
});

CodePudding user response:

You can simulate it with setTimeout, I further provided a mock response so after 1000ms it will send a Promise with this user array

const getData = () => {
    return new Promise((resolve, reject) => {
        setTimeout(resolve({
            users: [
                { name: "Michael" },
                { name: "Sarah" },
                { name: "Bill" },
            ]
        }), 1000)
    })
}

CodePudding user response:

This is what I do when there is a function making use of console.log and I want to suppress (or monitor) console output:

Sample function

function hasData(data) {
  console.log(data);
  return !!data;
}

Test suite

describe('Testing hasData', () => {
  it('should return true', () => {
    // save original function
    const __log = console.log;
    let hasConsoleLog = false;

    // override function
    console.log = () => hasConsoleLog = true;

    expect( hasData({ foo: true }) ).toBe(true);
    expect( hasConsoleLog ).toBe(true);

    // restore original function
    console.log = __log;
  });
});

If you can override got.post to something like:

got.post = async (url, data) => {
  return res;   // implement your mock-up response, here
};

then you can inject a testable API.

  • Related