Я ищу способ запустить приложение NestJS с поддельными поставщиками. Это необходимо для тестирования контракта с провайдером, потому что услугу нужно запускать изолированно. При использовании библиотеки Pact при тестировании провайдера предполагается, что сервис провайдера уже запущен. Он должен иметь возможность отправлять HTTP-запросы к фактическому серверу (при необходимости с фиксацией некоторых зависимостей). PactJS
Я просмотрел документацию по NestJS, и ближайшее решение, которое я могу найти, вставлено ниже. Насколько я могу судить, это решение сообщает модулю о необходимости замены любого поставщика с именем CatsService на catsService. Теоретически это сработает для целей тестирования контрактов с поставщиками, но я не думаю, что это позволяет запускать все приложение, только модуль. В документации нет упоминания о возможности запускать приложение на определенном порту с помощью модуля тестирования. Я попытался вызвать 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();
});
});
Используя 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);
}
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Начиная с версии 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-запросы вместо того, чтобы полагаться на супертесты. (В этом примере я использую стандартную http-библиотеку nodejs.)
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());
Большое спасибо!
Я только что понял, что часть про
listenAsyncустарела, а остальное у меня работает. Я также могу запросить сайт в браузере во время выполнения теста. Я использую версию 5.3.5