NestJs - 如何对 DTO 进行单元测试?

Jim*_*myB 13 javascript node.js nestjs

我请求你的帮助。我创建了一个看起来像这样的 DTO(这是一个较小的版本):

export class OfImportDto {

    @IsString({
        message: "should be a valid product code"
    })
    productCode: string;

    @IsString({
        message: "Enter the proper product description"
    })
    productDescription: string;

    @IsDateString({
        message: "should be a valid date format, for example : 2017-06-07T14:34:08+04:00"
    })
    manufacturingDate : Date

    @IsInt({
        message: "should be a valid planned quantity number"
    })
    @IsPositive()
    plannedQuantity: number;
Run Code Online (Sandbox Code Playgroud)

问题是我要求通过单元测试而不是 E2E 测试来测试这一点。我不知道该怎么做。例如,我想进行单元测试 1/ 如果我的产品代码是一个字符串,则应该创建一个字符串,如果不是,则抛出异常 2/ 如果我的产品描述是一个字符串,则应该创建一个字符串,如果不,抛出我的异常......等等。

那么,我可以制作一个spec.ts 文件来测试它吗?如果是,怎么办?如果没有,是否最好在 service.spec.ts 中测试它?如果是这样,怎么办?

非常感谢,任何帮助都会非常有帮助:)

Yog*_*ity 23

您应该创建一个单独的 DTO 特定文件,例如of-import.dto.spec.tsDTO 的单元测试。让我们看看如何在 Nest.js 中逐步测试 DTO。


TLDR:您的 DTO 的单元测试

要逐行理解它,请继续阅读:

it('should throw when the planned quantity is a negative number.', async () => {
  const importInfo = { productCode: 4567, plannedQuanity: -10 }
  const ofImportDto = plainToInstance(OfImportDto, importInfo)
  const errors = await validate(ofImportDto)
  expect(errors.length).not.toBe(0)
  expect(stringified(errors)).toContain(`Planned Quantity must be a positive number.`)
}
Run Code Online (Sandbox Code Playgroud)

创建一个普通对象来测试

以下是您想要测试验证的对象:

const importInfo = { productCode: 4567, plannedQuanity: -10 }
Run Code Online (Sandbox Code Playgroud)

如果您的测试对象有嵌套对象或者太大,您可以跳过这些复杂的属性。我们将看看如何处理这个问题。


将测试对象转换为DTO类型

使用包plainToinstace()中的函数class-transformer

const ofImportDto = plainToInstance(OfImportDto, importInfo)
Run Code Online (Sandbox Code Playgroud)

这会将您的普通测试对象转换为 DTO 类型的对象,即OfImportDto.

如果您的 DTO 中有任何转换(例如修剪属性值的空间),它们将在此时应用。如果您只想测试转换,您现在可以断言,不必调用以下validate()函数来测试转换。


模拟验证

使用包validate()中的函数class-validator

const errors = await validate(ofImportDto)
Run Code Online (Sandbox Code Playgroud)

如果您在创建测试对象时跳过了某些属性,则可以按如下方式处理:

const errors = await validate(ofImportDto, { skipMissingProperties: true })
Run Code Online (Sandbox Code Playgroud)

现在验证将忽略缺失的属性。


断言错误

断言errors数组不为空并且包含您的自定义错误消息:

expect(errors.length).not.toBe(0)
expect(stringified(errors)).toContain(`Planned Quantity must be a positive number.`)
Run Code Online (Sandbox Code Playgroud)

stringified()是一个帮助函数,用于将errors对象转换为 JSON 字符串,因此我们可以搜索它是否包含我们的自定义错误消息:

export function stringified(errors: ValidationError[]): string {
  return JSON.stringify(errors)
}
Run Code Online (Sandbox Code Playgroud)

就是这样!希望有帮助。


Jay*_*iel 6

可以创建一个OfImportDTO.spec.ts文件(或任何原始文件的名称),但问题是,这里没有任何逻辑可供测试。Validator您可以做的最接近的事情是创建from的实例class-validator,然后实例化 the 的实例OfImportDto,然后检查该类是否通过验证。如果您向其中添加逻辑(例如具有特定功能的 getter 和 setter),那么它对于单元测试可能有意义,但除此之外,这基本上是一个被称为类的接口,因此它在运行时存在class-validator