【发布时间】:2020-04-20 20:20:12
【问题描述】:
我想进行单元测试,并为我想要测试的 Nest API 提供一些配置服务。启动应用程序时,我使用 joi 包验证环境变量。
我有多个用于数据库、服务器的配置服务……所以我首先创建了一个基础服务。这个能够读取环境变量,将原始字符串解析为所需的数据类型并验证值。
import { ConfigService } from '@nestjs/config';
import { AnySchema, ValidationResult, ValidationError } from '@hapi/joi';
export abstract class BaseConfigurationService {
constructor(protected readonly configService: ConfigService) {}
protected constructValue(key: string, validator: AnySchema): string {
const rawValue: string = this.configService.get(key);
this.validateValue(rawValue, validator, key);
return rawValue;
}
protected constructAndParseValue<TResult>(key: string, validator: AnySchema, parser: (value: string) => TResult): TResult {
const rawValue: string = this.configService.get(key);
const parsedValue: TResult = parser(rawValue);
this.validateValue(parsedValue, validator, key);
return parsedValue;
}
private validateValue<TValue>(value: TValue, validator: AnySchema, label: string): void {
const validationSchema: AnySchema = validator.label(label);
const validationResult: ValidationResult = validationSchema.validate(value);
const validationError: ValidationError = validationResult.error;
if (validationError) {
throw validationError;
}
}
}
现在我可以使用多个配置服务扩展此服务。为了简单起见,我将为此使用服务器配置服务。目前它只保存应用程序要监听的端口。
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as Joi from '@hapi/joi';
import { BaseConfigurationService } from './base.configuration.service';
@Injectable()
export class ServerConfigurationService extends BaseConfigurationService {
public readonly port: number;
constructor(protected readonly configService: ConfigService) {
super(configService);
this.port = this.constructAndParseValue<number>(
'SERVER_PORT',
Joi.number().port().required(),
Number
);
}
}
我发现多篇文章我应该只测试公共方法,例如
https://softwareengineering.stackexchange.com/questions/100959/how-do-you-unit-test-private-methods
所以我假设我不应该测试来自基本配置服务的方法。但我想测试扩展基础服务的类。我从这个开始
import { Test, TestingModule } from '@nestjs/testing';
import { ConfigService } from '@nestjs/config';
import { ServerConfigurationService } from './server.configuration.service';
const mockConfigService = () => ({
get: jest.fn(),
});
describe('ServerConfigurationService', () => {
let serverConfigurationService: ServerConfigurationService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ServerConfigurationService,
{
provide: ConfigService,
useFactory: mockConfigService
}
],
}).compile();
serverConfigurationService = module.get<ServerConfigurationService>(ServerConfigurationService);
});
it('should be defined', () => {
expect(serverConfigurationService).toBeDefined();
});
});
但正如您在第二个代码 sn-p 中看到的那样,我正在从构造函数中的基本服务调用函数。测试立即失败
ValidationError: "SERVER_PORT" 必须是数字
有没有一种方法可以对配置服务进行单元测试,尽管它们依赖于抽象基类和外部 .env 文件?因为我知道我可以创建一个mockConfigService,但我认为基类打破了这一点。我不知道如何修复这个测试文件。
【问题讨论】:
-
您是否尝试检查像
expect(serverConfigurationService).not.toThrow(ValidationError);这样的 trown 错误?
标签: node.js unit-testing jestjs nestjs