2

使用嵌套对象时,我很难让我的 ValidationPipe 在类验证器中工作。

例如,我有 NestedObject 格式:

{
    Data: '123',
    Value: 567
}

然后我创建了nested-object.ts 类:

import { IsNumber, IsNumberString, Min, MinLength } from 'class-validator';

export class NestedObject {
    @IsNumberString() @MinLength(2) public readonly Data: string;
    @IsNumber() @Min(2) public readonly Value: number;
}

然后我可以编写一个 Jest 测试用例来覆盖 ValidationPipe 中的这个嵌套对象,并验证数据。

嵌套对象.spec.ts

import { ArgumentMetadata, HttpStatus, ValidationPipe } from '@nestjs/common';
import { NestedObject } from './nested-object';

describe('NestedObject', () => {
    it('should be defined', () => {
        expect(new NestedObject()).toBeDefined();
    });

    it('should validate the NestedObject definition for JSON payload { Data: null, Value: 0 }', async () => {
        const target: ValidationPipe = new ValidationPipe({
            transform: true,
            whitelist: true,
            enableDebugMessages: true,
            errorHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY,
        });
        const metadata: ArgumentMetadata = {
            type: 'body',
            metatype: NestedObject,
            data: '',
        };
        const Expected: string[] = [
            'Data must be longer than or equal to 2 characters',
            'Data must be a number string',
            'Value must not be less than 2',
        ];
        await target.transform({ Data: null, Value: 0 }, metadata).catch((err) => {
            expect(err.getResponse().statusCode).toBe(HttpStatus.UNPROCESSABLE_ENTITY);
            expect(err.getResponse().message).toEqual(Expected);
        });
    });
});

上述测试通过。我已经创建了基本对象,这很好用。我的问题是当我现在尝试在另一个类中验证这个对象时。新的类验证有效,但嵌套对象无效。

父对象.ts

import { Type } from 'class-transformer';
import { IsString, MinLength, ValidateNested } from 'class-validator';

import { NestedObject } from './nested-object';

export class ParentObject {
    @IsString() @MinLength(1) public readonly FileName: string;

    @ValidateNested()
    @Type(() => NestedObject)
    public Child: NestedObject;
}

我现在期望我的 ParentObject 将是:

{
    FileName: 'abc.txt',
    Child: {
        Data: '123',
        Value: 567
    }
}

然后我为 ParentObject 编写测试用例。

父对象.spec.ts

import { ArgumentMetadata, HttpStatus, ValidationPipe } from '@nestjs/common';
import { NestedObject } from './nested-object';
import { ParentObject } from './parent-object';

describe('ParentObject', () => {
    it('should be defined', () => {
        expect(new ParentObject()).toBeDefined();
    });

    it('should validate the ParentObject & NestedObject for JSON payload { FileName: null, Child: { Data: null, Value: 0 } }', async () => {
        const target: ValidationPipe = new ValidationPipe({
            transform: true,
            whitelist: true,
            enableDebugMessages: true,
            errorHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY,
        });
        const metadata: ArgumentMetadata = {
            type: 'body',
            metatype: ParentObject,
            data: '',
        };
        const Expected: string[] = [
            'FileName must be longer than or equal to 1 characters',
            'FileName must be a string',
            'Child.Data must be longer than or equal to 2 characters',
            'Child.Data must be a number string',
            'Child.Value must not be less than 2',
        ];
        await target.transform({ FileName: null, Child: { Data: null, Value: 0 } }, metadata).catch((err) => {
            expect(err.getResponse().statusCode).toBe(HttpStatus.UNPROCESSABLE_ENTITY);
            expect(err.getResponse().message).toEqual(Expected);
        });
    });
});

测试失败。该测试仅返回 FileName 验证,而不是应该来自 NestedObject 的 3 个 Child 验证。

- Expected  - 3
+ Received  + 2

  Array [
-   "Child.Data must be longer than or equal to 2 characters",
-   "Child.Data must be a number string",
-   "Child.Value must not be less than 2",
+   "FileName must be longer than or equal to 1 characters",
+   "FileName must be a string",
  ]

验证运行并检测到 FileName 问题,但未发现 NestedObject 错误。使用 NestedObject 时我是否错误地构建了对象?我是否在测试中遗漏了一些东西来检查子节点?

4

0 回答 0