测试 NestJS 验证管道不起作用

时间:2021-03-17 20:43:22

标签: jestjs automated-tests nestjs

我有一个简单的类,我正在尝试使用 NestJS 和端到端测试来确保验证正常工作,但我无法使验证正常工作。如果我使用 Postman 或普通客户端发送数据,应用程序会以正确的错误响应。

API.dto.ts

import { IsNumber, IsPositive, IsString } from 'class-validator';
export class ApiDTO {
    @IsString() public readonly FileName:string;
    @IsNumber() @IsPositive() public readonly StatusCode:number;
    @IsNumber() @IsPositive() public readonly TimeOut:number;
}

端到端测试文件

import { Test, TestingModule } from '@nestjs/testing';
import * as request from 'supertest';

import { INestApplication, ValidationPipe } from '@nestjs/common';

import { AppModule } from '@APP/app.module';
import { ApiDTO } from './../../src/api/api.dto';

describe('ApiController (e2e)', () => {
    let app: INestApplication;

    beforeEach(async () => {
        const moduleFixture: TestingModule = await Test.createTestingModule({
            imports: [AppModule],
        }).compile();

        app = moduleFixture.createNestApplication();
        app.useGlobalPipes(new ValidationPipe());
        await app.init();
    });

    it('/api/test/ (POST) test to see data validation works', async done => {
        const RequestBody:ApiDTO = {
            FileName : 'README.md',
            StatusCode: 111,
            TimeOut: -25
        };
        const Expected:string = `${RequestBody.FileName} = ${RequestBody.StatusCode.toString()} after ${RequestBody.TimeOut.toString()}`;

        const ResponseData = await request(app.getHttpServer())
            .post('/api/test')
            .send(RequestBody)
            .set('Accept', 'application/json');

        // All of these will fail as the code returns a 200 OK, as it does not do the validation (TimeOut -25 should fail IsPositive())
        expect(ResponseData.status).toBe(400);
        expect(ResponseData.headers['content-type']).toContain('application/json');

        // This line caused the problem as body is an object
        //expect(ResponseData.body.length).toBeGreaterThan(2);

        expect(ResponseData.body.statusCode).toBe(400);
        expect(ResponseData.body.message[0]).toBe('TimeOut must be a positive number');
        expect(ResponseData.body.error).toBe('Bad Request');
        done();         
    });

});

在进行此调用时,我成功返回了 200。我的代码应该会失败,因为 TimeOut 是负数,它需要是 IsPositive()。服务和其他代码都在运行,只是没有验证。我在 beforeEach() 中添加了全局管道,所以不确定还有什么要检查的。

1 个答案:

答案 0 :(得分:0)

我在测试中发现了错误。一旦我将 ValidationPipe() 添加到应用程序定义中:

app = moduleFixture.createNestApplication();
app.useGlobalPipes(new ValidationPipe());   // <- This addition
await app.init();

这使验证能够正常运行。测试失败,因为我正在检查响应正文的长度,

it('/api/test/ (POST) test to see data validation works', async done => {
    ...
    expect(ResponseData.body.length).toBeGreaterThan(10);
    ...
    done();         
});

ResponseData.body 是一个对象,因此该对象的 .length 无效。消除这种期望解决了我的问题。

it('/api/test/ (POST) test to see data validation works', async done => {
    const RequestBody:ApiDTO = {
        FileName : 'README.md',
        StatusCode: 111,
        TimeOut: -25
    };
    const Expected:string = `${RequestBody.FileName} = ${RequestBody.StatusCode.toString()} after ${RequestBody.TimeOut.toString()}`;

    const ResponseData = await request(app.getHttpServer())
        .post('/api/test')
        .send(RequestBody)
        .set('Accept', 'application/json');

    expect(ResponseData.status).toBe(400);
    expect(ResponseData.headers['content-type']).toContain('application/json');
    
    expect(ResponseData.body.statusCode).toBe(400);
    expect(ResponseData.body.message[0]).toBe('TimeOut must be a positive number');
    expect(ResponseData.body.error).toBe('Bad Request');
    done();         
});