如何在使用 jest 和 supertest 的集成测试中模拟 redis createClient 函数的实现?

JMi*_*Mir 5 redis node.js typescript supertest jestjs

我已经为 Redis 存储库创建了一个运行良好的单元测试:

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");
    });
});
Run Code Online (Sandbox Code Playgroud)

在这里我收到了我的mockedRedisClient,一切正常,我可以嘲笑我的行为。但是在使用 supertest 的集成测试中,具有相同的实现和相同的模拟过程,它根本不起作用,它不采用假实现:

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"
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

使用这个,createClient 被模拟,但没有实现。它忽略后来的修改,例如.mockReturnValue。采用不同的方法,我可以在模拟声明中对实现进行硬编码,执行以下操作:

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

但这是硬编码的,我无法更改我想要评估不同行为的每个测试的实现。有人知道为什么会发生这种情况吗?Supertest 不允许我在运行时更改实现?