简体   繁体   English

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

[英]Injecting Mocks in NestJS Application for Contract Testing

Issue 问题

I'm looking for a way to bring up a NestJS application with mocked providers. 我正在寻找一种通过模拟提供程序启动NestJS应用程序的方法。 This is necessary for provider contract tests because a service needs to be brought up in isolation. 这对于提供者合同测试是必需的,因为需要单独启动服务。 Using the Pact library, testing the provider assumes that the provider service is already running. 使用Pact库,测试提供程序时会假定提供程序服务已在运行。 It needs to be able to make HTTP requests against the actual server (with some dependencies mocked if necessary). 它需要能够对实际服务器发出HTTP请求(必要时可以模拟某些依赖项)。 PactJS PactJS

Current Research 目前的研究

I've looked into the docs for NestJS and the closest solution I can find is pasted below. 我已经研究了NestJS的文档,下面找到了我能找到的最接近的解决方案。 From what I can tell, this solution tells the module to replace any provider called CatsService with catsService . 据我所知,该解决方案告诉模块将所有称为CatsService提供程序CatsServicecatsService This theoretically would work for provider contract testing purposes, but I don't think this allows for the entire app to be brought up, just a module. 从理论上讲,这可以用于提供者合同测试,但是我认为这不能允许整个应用程序启动,而只是一个模块。 There is no mention in the docs for being able to bring up the app on a specific port using the testing module. 在文档中没有提及能够使用测试模块在特定端口上启动应用程序。 I've tried to call app.listen on the returned app object and it fails to hit a breakpoint placed right after the call. 我尝试在返回的应用程序对象上调用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 Example Java示例

Using Spring a configuration class, mocks can be injected into the app when running with the "contract-test" profile. 使用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);
  }
} 

Update 更新

Since version 4.4 you can also use listen since it now also returns a Promise . 从4.4版开始,您还可以使用listen因为它现在还会返回Promise


You have to use the method listenAsync instead of listen so that you can use it with await : 您必须使用方法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);
        ^^^^^^^^^^^^^^^^^^^^^
});

Then you can make actual http requests instead of relying on supertest. 然后,您可以发出实际的http请求,而不必依赖supertest。 (I am using the nodejs standard http library in this example.) (在此示例中,我使用的是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();
    });
  });
});

Don't forget to close the application or otherwise your test will run until closed manually. 不要忘记关闭应用程序,否则测试将一直运行,直到手动关闭。

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

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

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