4

I have created a unit test for a redis repository that works fine:

import { RedisSecretRepository } from "../../../../src/adapters/repositories/RedisSecretRepository";
import { Secret } from "../../../../src/domain/models/Secret";
import { UrlId } from "../../../../src/domain/models/UrlId";
import { SecretNotFoundInRepositoryError } from "../../../../src/domain/models/errors/SecretNotFoundInRepository";

jest.mock("redis");
import { createClient } from "redis";
const mockedCreateClient = createClient as jest.MockedFunction<any>;

describe("Redis Secret Repository", () => {
    it("should get a secret by urlId", () => {
        const mockedRedisClient = {
            connect: jest.fn(),
            get: jest.fn(async () => "123qwe"),
            on: jest.fn(),
        };
        mockedCreateClient.mockReturnValue(mockedRedisClient);

        const redisSecretRepository = new RedisSecretRepository();

        expect(redisSecretRepository.getSecretByUrlId(new UrlId("123456qwerty")))
            .resolves.toEqual(new Secret("123qwe"));
        expect(mockedRedisClient.get).toBeCalledTimes(1);
        expect(mockedRedisClient.get).toBeCalledWith("123456qwerty");
    });
});

and here I receive my mockedRedisClient and everything works good, I can mock my behaviour. But in the integration test using supertest, with the same implementation and same mocking procedure, it simply does not work, it does not take the fake implementation:

import supertest from "supertest";
import server from "../../src/server";
const request = supertest(server.app);

jest.mock("redis");
import { createClient } from "redis";
const mockedCreateClient = createClient as jest.MockedFunction<any>;

describe("Get Secrets By Id Integration Tests", () => {
    it("should retrieve a secret", async () => {
        const mockedRedisClient = {
            connect: jest.fn(),
            get: jest.fn(async () => "123qwe"),
            on: jest.fn(),
        };
        mockedCreateClient.mockReturnValue(mockedRedisClient);

        const res = await request
            .get("/api/v1/secrets/123456qwerty");

        expect(createClient).toBeCalledTimes(3);
        console.log(res.body);
        expect(res.status).toBe(200);
        expect(res.body).toEqual({
            secret: "123qwe"
        });
    });
});

Using this, createClient is mocked, but with no implementation. It is ignoring later modifications like .mockReturnValue. In a different approach, I could hardcode the implementation in the mock declaration doing this:

import { createClient } from "redis";
jest.mock("redis", () => {
    return {
        createClient: () => {
            return {
                connect: jest.fn(),
                get: jest.fn(async () => "123qwe"),
                on: jest.fn(),
            }
        }
    }
});

but this is hardcoded, I cannot change the implementation for each test where I want to assess different behaviors. anyone knows why this happens? Supertest does not allow me to change implementations on runtime?

JMir
  • 137
  • 1
  • 10

0 Answers0