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
我已添加到 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