1

I'm using TypeORM.
It works fine at the local with real DB connection.

But when I run the test with Jest, the test gets failed.
I mocked the TypeORM method I needed, and expected all these methods to be called.

Test is failing on expect(typeorm.getRepository(Covid).save).toHaveBeenCalled();
it is not being called.

I cannot understand why this test code is not calling.

Does anyone know the solution?

Here is the code.

describe('getCoronaData', () => {
  it('should get a Covid Status data and return it', async () => {
    typeorm.getRepository = jest.fn().mockReturnValue({
      findOne: jest.fn().mockResolvedValue(null),
      create: jest.fn(),
      save: jest.fn(),
    });

    await getCoronaData();

    expect(typeorm.getRepository).toHaveBeenCalledWith(Covid);
    expect(typeorm.getRepository(Covid).findOne).toHaveBeenCalled();
    expect(typeorm.getRepository(Covid).save).toHaveBeenCalled(); // this expect result is making an error
                                                                  // Expected number of calls: >= 1
                                                                  // Received number of calls:    0
  });
});

export const getCoronaData = async () => {
  try {
    // Just a fake data
    const covidStatus = [
      {
        city: 'city',
        totalCases: '100',
        increasedCases: '100',
        date: 'time',
      },
    ];
    const covidRepository = getRepository(Covid);
    covidStatus.forEach(async (status) => {
      const exist = await covidRepository.findOne({
        where: { city: status.city },
      });
      if (!exist) {
        // expecting save() method at this part to be called, but it fails
        return await covidRepository.save(
          covidRepository.create({
            city: status.city,
            totalCases: status.totalCases,
            increasedCases: status.increasedCases,
            date: status.time,
          })
        );
      } else {
        return await covidRepository.save([
          {
            id: exist.id,
            totalCases: status.totalCases,
            increasedCases: status.increasedCases,
            date: status.time,
          },
        ]);
      }
    });
  } catch (err) {
    console.error(err);
    return;
  }
};
americano
  • 11
  • 2

1 Answers1

0

Self-answer

I found the problem why the test failing. forEach() method should not be used with async/await.
so I just changed the code using Promise.all() and map()

await Promise.all(
      covidStatus.map(async (status) => {
        const exist = await covidRepository.findOne({
          where: { city: status.city },
        });
        if (!exist) {
          const newData = covidRepository.create({
            city: status.city,
            totalCases: status.totalCases,
            increasedCases: status.increasedCases,
            date: $standardTime,
          });
          return covidRepository.save(newData);
        } else {
          return covidRepository.save([
            {
              id: exist.id,
              totalCases: status.totalCases,
              increasedCases: status.increasedCases,
              date: $standardTime,
            },
          ]);
        }
      })
    );

Or

    for (const status of covidStatus) {
      const exist = await covidRepository.findOne({
        where: { city: status.city },
      });
      if (!exist) {
        const newData = covidRepository.create({
          city: status.city,
          totalCases: status.totalCases,
          increasedCases: status.increasedCases,
          date: $standardTime,
        });
        return covidRepository.save(newData);
      } else {
        return covidRepository.save([
          {
            id: exist.id,
            totalCases: status.totalCases,
            increasedCases: status.increasedCases,
            date: $standardTime,
          },
        ]);
      }
    }

I found this solution from Here.

using forEach and async/await, behaves different for node and Jest

americano
  • 11
  • 2
  • Async testing often needs a done() function call as part of the test. Once you map from a promise, this is different, but without that, doing a basic async/await, should have the done() function. – Steven Scott Jan 28 '21 at 14:45