如何在 Nestjs 中模拟 Jest Redis

Tje*_*123 3 unit-testing redis node.js jestjs nestjs

我正在开发 NestJs 应用程序,并为我的authenticateUser函数编写了单元测试user.service.ts。它已在我的本地计算机中通过。但是当我将其部署到服务器并运行单元测试时,我收到错误Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED。似乎 redis 模拟不起作用。我应该如何模拟 redis 并解决这个工作问题?

用户服务.ts

async authenticateUser(authDto: AuthDTO): Promise<AuthResponse> {
    try {
     const userData = await this.userRepository.findOne({msisdn});
     if(userData){
         await this.redisCacheService.setCache(msisdn, userData);
     }
    } catch (error) {
        console.log(error)
    }
}
Run Code Online (Sandbox Code Playgroud)

redisCache.service.ts

export class RedisCacheService {
  constructor(
    @Inject(CACHE_MANAGER) private readonly cache: Cache,
  ) {}

  async setCache(key, value) {
    await this.cache.set(key, value);
  }
}
Run Code Online (Sandbox Code Playgroud)

用户.服务.规格.ts

describe('Test User Service', () => {
  let userRepository: Repository<UserEntity>;
  let userService: UserService;
  let redisCacheService: RedisCacheService;
  let cacheManager: any;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UserService,
        UserEntity,
        RedisCacheService,
        {
          provide: getRepositoryToken(UserEntity),
          useClass: registeredApplicationRepositoryMockFactory,
        },
      ],
      imports: [CacheModule.register({})],
    }).compile();

    userService = module.get<UserService>(UserService);
    userRepository = module.get<Repository<UserEntity>>(
      getRepositoryToken(UserEntity),
    );
    redisCacheService = module.get<RedisCacheService>(RedisCacheService);
    cacheManager = module.get<any>(CACHE_MANAGER);
  });

  it('authenticateUser should return success response', async () => {
    const userEntity = { id: 1, name: 'abc', age: 25 };
    const mockSuccessResponse = new AuthResponse(
      HttpStatus.OK,
      STRING.SUCCESS,
      `${STRING.USER} ${STRING.AUTHENTICATE} ${STRING.SUCCESS}`,
      {},
    );

    jest.spyOn(userRepository, 'findOne').mockResolvedValueOnce(userEntity);
    jest.spyOn(redisCacheService, 'setCache').mockResolvedValueOnce(null);

    expect(await userService.authenticateUser(mockAuthBody)).toEqual(mockSuccessResponse);
  });
});
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

小智 8

您可以使用自定义提供程序来模拟 CACHE_MANAGER:

import { CACHE_MANAGER } from '@nestjs/common';
import { Cache } from 'cache-manager';

describe('AppService', () => {
  let service: AppService;
  let cache: Cache;

  beforeEach(async () => {
    const app = await Test.createTestingModule({
      providers: [
        AppService,
        {
          provide: CACHE_MANAGER,
          useValue: {
            get: () => 'any value',
            set: () => jest.fn(),
          },
        },
      ],
    })
    .compile();

    service = app.get<AppService>(AppService);
    cache = app.get(CACHE_MANAGER);
  });

  // Then you can use jest.spyOn() to spy and mock

  it(`should cache the value`, async () => {
    const spy = jest.spyOn(cache, 'set');

    await service.cacheSomething();

    expect(spy).toHaveBeenCalledTimes(1);
    expect(spy.mock.calls[0][0]).toEqual('key');
    expect(spy.mock.calls[0][1]).toEqual('value');
  });

  it(`should get the value from cache`, async () => {
    const spy = jest.spyOn(cache, 'get');

    await service.getSomething();

    expect(spy).toHaveBeenCalledTimes(1);
  });

  it(`should return the value from the cache`, async () => {
    jest.spyOn(cache, 'get').mockResolvedValueOnce('value');
    
    const res = await service.getSomething();

    expect(res).toEqual('value');
  }),
});
Run Code Online (Sandbox Code Playgroud)

有关自定义提供商的更多详细信息:https ://docs.nestjs.com/fundamentals/custom-providers

还有两件事,对于单元测试,您不应该导入模块,而应该模拟依赖项。正如 Daniel 所说,UserService 不是使用 CACHE_MANAGER 而是使用 RedisCacheService,因此您应该模拟 RedisCacheService。

通常最好的办法是只提供您正在测试的服务并模拟依赖项。