rablentain
rablentain

Reputation: 6715

How to mock nestjs-redis with jest

I am trying to mock and spy on the redis set method in my nestjs setup, but I don't think that it is working as it should.

    const mockRedis = {
      set: jest.fn().mockResolvedValue(undefined),
    };

    const mockRedisService = {
      getClient: jest.fn(() => mockRedis),
    };

    beforeEach(async () => {
      const moduleRef = await Test.createTestingModule({
        providers: [
          { provide: RedisService, useValue: mockRedisService },
        ],
      }).compile();
    });

    it('...',() => {
      const redisSetSpy = jest.spyOn(mockRedis, 'set');

      myTestedMethod();

      expect(redisSetSpy).toBeCalledWith(/* args here */);
    })

I suspect that it is not possible to use spyOn with a nested method as set in this context? How should I mock redis to be able to use spyOn on set? The library used for redis in this case is nestjs-redis.

Upvotes: 2

Views: 2421

Answers (1)

Baboo
Baboo

Reputation: 4258

You don't have to use spyOn to check the arguements that have been passed to the function. You can simply create a jest.fn():

let mockRedisSet;

// Function that creates the testing app.
const createApp = () => {
  const mockRedis = {
    set: mockRedisSet,
  };

  const mockRedisService = {
    getClient: jest.fn(() => mockRedis),
  };

  const moduleRef = await Test.createTestingModule({
    providers: [{ provide: RedisService, useValue: mockRedisService }],
  }).compile();
};

// For each test, set default mock and create testing app.
beforeEach(async () => {
  mockRedisSet = jest.fn().mockResolvedValue(undefined);
  createApp();
});

describe("...", () => {
  // For each sub tests, set default mock and create testing app.
  beforeEach(async () => {
    mockRedisSet = jest.fn().mockResolvedValue(/* Specific value for sub tests */);
    createApp();
  });

  it("...", () => {
    myTestedMethod();

    // Check which arguments was passed to the mock function.
    expect(mockRedisSet).toHaveBeenCalledWith(/* args here */);
  });
});

Creating a mock is much simpler this way as you only have to create the mocked objects and test the functions the use.

Here your spy is mockRedisSet and I reorganized your testing file so the spy function has a default value that can be overridden for specific tests. You have more control on the testing value and a default value reset for each tests so that tests don't interfer with each other.

Upvotes: 2

Related Questions