NestJS 模拟构造函数调用 HashiCorpVault

NestJS Mock Constructor call to HashiCorpVault

我已添加到 Hashicorp 保险库的连接(在映射器服务中)以获取用于加密的密钥。我需要在我的服务的构造函数中获取密钥。我的测试现在失败了,因为当映射器服务被实例化时,构造函数被调用并且 vault 不可用。如果我模拟整个服务,那么我的所有其他测试都将不起作用。所以我只需要模拟构造函数调用,这样它就不会在每次测试之前触发。

mapper.service.ts

@Injectable()
export class Mapper {
key;
encryptionKey;

constructor(private vault: VaultService) {
    this.setKey(); // I do not want this to happen in my tests
}

async setKey() {

    this.vault.getValueFromVault('soapCredentials', 'encryptionKey').then(async (response) => { 
        this.encryptionKey = response;
        console.log('this.encryptionKey', this.encryptionKey)
        try {
        this.key = (await promisify(scrypt)(this.encryptionKey, 'salt', 32)) as Buffer;
        } catch {
            throw new Error('Encryption set error')
        } 
    }).catch( err => {
        throw new Error(err);
    });   
}

mapper.service.spec.ts

describe('Mapper', () => {
let mapper: EnrichementMapper;
let vault: VaultService;

beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
        providers: [
            EnrichementMapper,
            VaultService
        ],
    }).compile();
    mapper = module.get<EnrichementMapper>(EnrichementMapper);
    vault = module.get<VaultService>(VaultService);
});

it('should be defined', () => {
    expect(mapper).toBeDefined();
});
.... 20 more tests

甚至 'should be defined' 测试也失败了,因为正在调用构造函数并且正在调用 this.setKey()。当它尝试 运行 this.vault.getValueFromVault 时会导致错误。我如何模拟构造函数以使其不触发?

你走在正确的轨道上。您要做的是确保您的 Vault 是一个注入服务,就像您在构造函数中所做的那样。这样,您可以提供一个模拟来替换它。

我发现执行此操作的最简单方法是仅在模拟中定义我需要的函数,以便它们 return 设置数据并继续您的测试。

在您的 beforeEach() 中,您将 vault 服务替换为虚假服务的 Jest 定义。

describe('Mapper', () => {
    let mapper: EnrichementMapper;
    let vault: VaultService;

    beforeEach(async () => {
        const FakeVaultService = {
            provide: VaultService,
            useFactory: () => ({
                setKey: jest.fn().mockResolvedValue('Key/Token, whatever'),
            }),
        };

        const module: TestingModule = await Test.createTestingModule({
            providers: [
                EnrichementMapper,
                FakeVaultService
            ],
        }).compile();
        mapper = module.get<EnrichementMapper>(EnrichementMapper);
        vault = module.get<VaultService>(VaultService);
    });

    it('should be defined', () => {
        expect(mapper).toBeDefined();
    });
    
    .... 20 more tests
});

当您的代码调用 setKey 时,将调用 FakeVaultService 代码。 mockResolvedValue 使其异步,因此您也可以进行适当的代码处理。 Jest Mock reference