user9855821
user9855821

Reputation:

Jest test with SpyOn

How can I test this code in jest using spyOn? Can someone help me with a proper solution?

const controller = {};

controller.fetchCars = async (req, res) => {
  const result = await getCarsService(req.body);
  res.json(result);
};

I've tried this:

    it('fetchCars should call getCarsService', () => {
      const spy = jest.spyOn(carsController, 'getCarsService').mockImplementation(() => {});
      const req = {};
      const res = {};

      carsController.fetchCars(req, res);
      expect(spy).toBeCalled()
      spy.mockRestore();
    });

and gives me this error: Cannot spy the getCarsService property because it is not a function; undefined given instead

getCarsService() it's imported from /services and it looks like this:

export const getCarsService = async body => {
  const carsReqConfig = {
    headers: fetchApi.newHeaderWithToken(CAR_JWT, SITE_ID)
  };
  const result = await instance.post(
    `${API_GATEWAY_URL}${CAR_ENDPOINT}/search`,
    body,
    carsReqConfig
  );
  const cars = result?.data?.results.filter(
    car => car.orderType === 'AI'
  );
  const formatedResponse = formatCarSearchRes(cars);
  return formatedResponse;
};

Upvotes: 1

Views: 1409

Answers (1)

Win
Win

Reputation: 5584

The easiest solution would be to separate your code into each file and then just use jest.mock to mock the getCarsService method.

index.js

import getCarsService from './getCarsService';

const controller = {
    fetchCars: async (req, res) => {
        const result = await getCarsService(req.body);
        return res.json(result);
    },
};

export default controller;

getCarsService.js

function getCarsService(body) {
    return new Promise(resolve => resolve(1));
}

export default getCarsService;

index.spec.js

import controller from './index';
import getCarsService from './getCarsService';

jest.mock('./getCarsService', () => jest.fn().mockResolvedValue(1));

it('fetchCars should call getCarsService', async () => {
    const req = {
        hello: 'world',
    };
    const res = {
        json: jest.fn(),
    };

    await controller.fetchCars(req, res);
    expect(getCarsService).toBeCalled();
    expect(res.json).toBeCalledWith(1);
});

If you are dead set on using a spy you can do it like this by spying on the default export.

import controller from './index';
import * as getCarsService from './getCarsService';

it('fetchCars should call getCarsService', async () => {
    const req = {
        hello: 'world',
    };
    const res = {
        json: jest.fn(),
    };

    const spy = jest.spyOn(getCarsService, 'default');
    spy.mockResolvedValue(2);

    await controller.fetchCars(req, res);
    expect(res.json).toBeCalledWith(2);
});

Upvotes: 1

Related Questions