繁体   English   中英

在NestJS应用程序中注入样本以进行合同测试

[英]Injecting Mocks in NestJS Application for Contract Testing

问题

我正在寻找一种通过模拟提供程序启动NestJS应用程序的方法。 这对于提供者合同测试是必需的,因为需要单独启动服务。 使用Pact库,测试提供程序时会假定提供程序服务已在运行。 它需要能够对实际服务器发出HTTP请求(必要时可以模拟某些依赖项)。 PactJS

目前的研究

我已经研究了NestJS的文档,下面找到了我能找到的最接近的解决方案。 据我所知,该解决方案告诉模块将所有称为CatsService提供程序CatsServicecatsService 从理论上讲,这可以用于提供者合同测试,但是我认为这不能允许整个应用程序启动,而只是一个模块。 在文档中没有提及能够使用测试模块在特定端口上启动应用程序。 我尝试在返回的应用程序对象上调用app.listen ,但它未达到调用后立即放置的断点。

import * as request from "supertest";
import { Test } from "@nestjs/testing";
import { CatsModule } from "../../src/cats/cats.module";
import { CatsService } from "../../src/cats/cats.service";
import { INestApplication } from "@nestjs/common";

describe("Cats", () => {
  let app: INestApplication;
  let catsService = { findAll: () => ["test"] };

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [CatsModule]
    })
      .overrideProvider(CatsService)
      .useValue(catsService)
      .compile();

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

  it(`/GET cats`, () => {
    return request(app.getHttpServer())
      .get("/cats")
      .expect(200)
      .expect({
        data: catsService.findAll()
      });
  });

  afterAll(async () => {
    await app.close();
  });
});

Java示例

使用Spring配置类,可以在使用“合同测试”配置文件运行时将模拟注入到应用程序中。

@Profile({"contract-test"})
@Configuration
public class ContractTestConfig {

  @Bean
  @Primary
  public SomeRepository getSomeRepository() {
    return mock(SomeRepository.class);
  }

  @Bean
  @Primary
  public SomeService getSomeService() {
    return mock(SomeService.class);
  }
} 

更新

从4.4版开始,您还可以使用listen因为它现在还会返回Promise


您必须使用方法listenAsync而不是listen以便可以在await使用它:

beforeAll(async () => {
  const moduleFixture = await Test.createTestingModule({
    imports: [AppModule],
  })
    .overrideProvider(AppService).useValue({ root: () => 'Hello Test!' })
    .compile();

  app = moduleFixture.createNestApplication();
  await app.init();
  await app.listenAsync(3000);
        ^^^^^^^^^^^^^^^^^^^^^
});

然后,您可以发出实际的http请求,而不必依赖supertest。 (在此示例中,我使用的是nodejs标准的http库。)

import * as http from 'http';

// ...

it('/GET /', done => {
  http.get('http://localhost:3000/root', res => {
    let data = '';
    res.on('data', chunk => data = data + chunk);
    res.on('end', () => {
      expect(data).toEqual('Hello Test!');
      expect(res.statusCode).toBe(200);
      done();
    });
  });
});

不要忘记关闭应用程序,否则测试将一直运行,直到手动关闭。

afterAll(() => app.close());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM