Search code examples
typescriptjestjsmockingnestjsts-jest

how to mock different values for same function jest?


I have a function where I take a time range as input and fetch 2 rows from my db. I need to get the difference of the field between the 1st and last data entry in the given range.

My function

async getUsage(start: Date, id: number) {
    const initial = await this.datarepo
      .createQueryBuilder('data')
      .where('data.deviceId = :id and data.RTC > :start')
      .setParameter('id', id)
      .setParameter('start', start)
      .orderBy('data.RTC', 'ASC')
      .getOne();

    const final = await this.datarepo
      .createQueryBuilder('data')
      .where('data.deviceId = :id and data.RTC > :start')
      .setParameter('id', id)
      .setParameter('start', start)
      .orderBy('data.RTC', 'DESC')
      .getOne();

    if (!final) return 0;
    const usage = final.reading- initial.reading;
    return usage;
  }

When I try to mock the function, I am getting the same data for each call even when I use mockResolvedValueOnce()

beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        DataService,
        {
          provide: getRepositoryToken(dataentity),
          useValue: {
            create: jest.fn(),
            save: jest.fn(),
          },
        },
      ],
    }).compile();

    service = module.get<DataService>(DataService);
    datarepo= module.get(getRepositoryToken(dataentity));
  });

it('gives the difference between energy readings for the given time range', async () => {
    datarepo.createQueryBuilder = jest.fn(() => ({
      where: jest.fn().mockReturnThis(),
      setParameter: jest.fn().mockReturnThis(),
      orderBy: jest.fn().mockReturnThis(),
      getOne: jest
        .fn()
        .mockResolvedValueOnce(usageStart)
        .mockResolvedValueOnce(usageEnd),
    }));
    const result = await service.getUsage(new Date('2021-03-01T11:57:00.000Z'), 981);
    expect(result).toEqual(5);
  });
const usageStart = {
  reading: 70,
  RTC: '2021-03-01T11:57:45.000Z',

};

const usageEnd = {
  reading: 75,
  RTC: '2021-03-01T12:57:45.000Z',
};

I should get 5 as the result but I am getting 0

 expect(received).toEqual(expected) // deep equality

    Expected: 5
    Received: 0

Solution

  • You mock datarepo.createQueryBuilder as a function, the function will return an object with some mock functions include getOne function.

    You call this.datarepo.createQueryBuilder two times, it will return 2 different instances of the object. Then, getOne function always returns the first mock value - usageStart, because it never is called again.

    Let's create a mock object, then mock datarepo.createQueryBuilder will return that object:

          const queryBuilderMock = {
            where: jest.fn().mockReturnThis(),
            setParameter: jest.fn().mockReturnThis(),
            orderBy: jest.fn().mockReturnThis(),
            getOne: jest
              .fn()
              .mockResolvedValueOnce(usageStart)
              .mockResolvedValueOnce(usageEnd),
          }
          
          datarepo.createQueryBuilder = jest.fn(() => queryBuilderMock);
    

    As you see, datarepo.createQueryBuilder always return queryBuilderMock object.