You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SuperTest E2E测试GraphQL API时TypeORM实体校验器不生效

NestJS E2E测试中GraphQL接口校验失效问题

基本信息

  • 技术栈:NestJS + GraphQL + TypeORM
  • 问题现象:用SuperTest对GraphQL API做E2E测试时,实体字段上配置的@IsURL()、@IsNotEmpty()等class-validator校验规则完全不触发。
  • 正常场景表现:应用本地启动后,通过GraphQL Playground、curl请求访问接口时校验逻辑完全正常。

现象对比

正常运行时的接口响应

传入合法URL,接口正常返回创建成功的数据:

{
  "data": {
    "createProject": {
      "uuid": "da1d8f48-2109-4629-a10f-67a5a7c3a5a2",
      "title": "f",
      "description": "descriptions",
      "releaseDate": null,
      "websiteURL": "www.f.com",
      "slug": "f"
    }
  }
}

传入非法URL,接口正常抛出400校验错误:

{
  "errors": [
    {
      "message": "Bad Request Exception",
      "extensions": {
        "code": "BAD_USER_INPUT",
        "response": {
          "statusCode": 400,
          "message": [
            "websiteURL must be an URL address"
          ],
          "error": "Bad Request"
        }
      }
    }
  ],
  "data": null
}

E2E测试中的异常响应

测试用例中传入非法URL时,接口不抛错,非法数据直接落库创建成功,返回结果如下:

{
  data: {
    createProject: {
      uuid: '2be26d1f-d6b9-4a82-addc-778e497cdb1e',
      title: 'URL Project',
      description: 'Sit aut iusto dolor sunt.',
      releaseDate: null,
      websiteURL: 'invalid url',
      slug: 'url-project'
    }
  }
}

相关代码片段

测试初始化逻辑

beforeEach(async () => {
  const moduleFixture: TestingModule = await Test.createTestingModule({
    imports: [
      TypeOrmModule.forRoot({
        ...testDataSourceOptions,
        entities: [],
        autoLoadEntities: true,
        dropSchema: true,
      }),
      AppModule,
    ],
  }).compile();

  const dataSource = new DataSource(testDataSourceOptions);
  await dataSource.initialize();
  await dataSource.runMigrations();

  app = moduleFixture.createNestApplication();
  await app.init();
});

异常场景测试用例

it('does not allow invalid urls', () => {
  const newURLProject = (title: string, websiteURL: string) => {
    const description = faker.lorem.sentence();
    const query = `
      mutation CreateProject {
        createProject(newProject: {
          title: "${title}",
          description: "${description}",
          websiteURL: "${websiteURL}"
        }) {
          uuid
          title
          description
          releaseDate
          websiteURL
          slug
        }
      }
    `;
    return { title, description, websiteURL, query };
  };

  const projectURL = newURLProject("URL Project", "invalid url")
  console.log(projectURL.websiteURL)

  return request(app.getHttpServer())
    .post('/graphql')
    .send({ query: projectURL.query })
    .expect(200)
    .expect(
      ({
        body: {
          errors: { errors }
        } 
      }) => {
        console.log(errors)
        expect(errors[0].extensions.response.statusCode).toEqual(400);
        expect(errors[0].extensions.response.message).toEqual(["websiteURL must be an URL address"]);
      }
    )
})

说明:DTO、实体类定义本身无问题,在非测试环境下运行完全符合预期,因此不贴这部分代码。


已尝试的解决手段

  • 替换请求库,改用supertest-graphql编写测试用例,问题复现,没有解决。
  • 后续考虑完全替换SuperTest框架,但改动成本较高,暂未推进。

求助

希望有遇到过同类问题的开发者提供排查方向或解决方案,感谢。

内容的提问来源于stack exchange,提问作者Bartosz Raubo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:30:54