1
votes

I am trying to figure out how to mock a call to Date.now with jest in my nestjs application.

I have a repository method that soft deletes a resource

async destroy(uuid: string): Promise<boolean> {
  await this.userRepository.update({ userUUID: uuid }, { deletedDate: Date.now() });
  return true;
}

to soft delete we just add a timestamp of when it was requested to be deleted

Following some discussions on here and other sites I came up with this test.

  describe('destroy', () => {
    it('should delete a user schemas in the user data store', async () => {
      const getNow = () => Date.now();
      jest
        .spyOn(global.Date, 'now')
        .mockImplementationOnce(() =>
          Date.now().valueOf()
        );
      const targetResource = 'some-uuid';
      const result = await service.destroy(targetResource);
      expect(result).toBeTruthy();
      expect(userRepositoryMock.update).toHaveBeenCalledWith({ userUUID: targetResource }, { deletedDate: getNow() });
    });
  });

I assumed that .spyOn(global.Date) mocked the entire global dat function , but the Date.now() in my repository is still returning the actual date rather than the mock.

My question is, is there a way to provide the mock return value of Date.now called in the repository from the test or should I just DI inject a DateProvider to the repository class which I can then mock from my test?

1

1 Answers

2
votes

jest.spyOn(Date, 'now') should work.

E.g.

userService.ts:

import UserRepository from './userRepository';

class UserService {
  private userRepository: UserRepository;
  constructor(userRepository: UserRepository) {
    this.userRepository = userRepository;
  }
  public async destroy(uuid: string): Promise<boolean> {
    await this.userRepository.update({ userUUID: uuid }, { deletedDate: Date.now() });
    return true;
  }
}

export default UserService;

userRepository.ts:

class UserRepository {
  public async update(where, updater) {
    return 'real update';
  }
}

export default UserRepository;

userService.test.ts:

import UserService from './userService';

describe('60204284', () => {
  describe('#UserService', () => {
    describe('#destroy', () => {
      it('should soft delete user', async () => {
        const mUserRepository = { update: jest.fn() };
        const userService = new UserService(mUserRepository);
        jest.spyOn(Date, 'now').mockReturnValueOnce(1000);
        const actual = await userService.destroy('uuid-xxx');
        expect(actual).toBeTruthy();
        expect(mUserRepository.update).toBeCalledWith({ userUUID: 'uuid-xxx' }, { deletedDate: 1000 });
      });
    });
  });
});

Unit test results with 100% coverage:

 PASS  stackoverflow/60204284/userService.test.ts
  60204284
    #UserService
      #destroy
        ✓ should soft delete user (9ms)

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------|---------|----------|---------|---------|-------------------
All files       |     100 |      100 |     100 |     100 |                   
 userService.ts |     100 |      100 |     100 |     100 |                   
----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.572s, estimated 11s

source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60204284