Во-первых, вы правильно используете providers
. Components
- это специфическая вещь Angular
, которой нет в Nest. Самое близкое, что у нас есть, это controllers
.
То, что вы должны делать для модульного теста, - это тестирование того, что возвращает единственная функция без углубления в саму кодовую базу. В приведенном вами примере вы хотели бы смоделировать ElasticSearchServices
с помощью jest.mock
и подтвердить возвращение метода PoolJobService
.
Nest предоставляет нам очень хороший способ сделать это с Test.createTestingModule
, как вы уже указали. Ваше решение будет выглядеть следующим образом:
PoolJobService.spec.ts
import { Test, TestingModule } from '@nestjs/testing'
import { PoolJobService } from './PoolJobService'
import { ElasticSearchService } from '../ElasticSearch/ElasticSearchService'
describe('PoolJobService', () => {
let poolJobService: PoolJobService
let elasticService: ElasticSearchService // this line is optional, but I find it useful when overriding mocking functionality
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
PoolJobService,
{
provide: ElasticSearchService,
useValue: {
getElasticSearchData: jest.fn()
}
}
],
}).compile()
poolJobService = module.get<PoolJobService>(PoolJobService)
elasticService = module.get<ElasticSearchService>(ElasticSearchService)
})
it('should be defined', () => {
expect(poolJobService).toBeDefined()
})
it('should give the expected return', async () => {
elasticService.getElasticSearchData = jest.fn().mockReturnValue({data: 'your object here'})
const poolJobs = await poolJobService.getPoolJobs()
expect(poolJobs).toEqual({data: 'your object here'})
})
Вы можете достичь той же функциональности с jest.spy
вместо mock
, но от вас зависит, как вы захотите реализовать эту функциональность.
Как основное правило, что бы ни было в вашем конструкторе, вам нужно будет его смоделировать, и пока вы его высмеиваете, все, что находится в конструкторе смоделированного объекта, можно игнорировать. Счастливого тестирования!
РЕДАКТИРОВАТЬ 6/27/2019
О том, почему мы высмеиваем ElasticSearchService
: модульное тестирование предназначено для тестирования определенного сегмента кода, а не для взаимодействия с кодом вне проверяемой функции. В этом случае мы тестируем функцию getPoolJobs
класса PoolJobService
. Это означает, что нам на самом деле не нужно изо всех сил и подключаться к базе данных или внешнему серверу, так как это может сделать наши тесты медленными / подверженными сбоям, если сервер не работает / изменяет данные, которые мы не хотим изменять. Вместо этого мы смоделируем внешние зависимости (ElasticSearchService
), чтобы вернуть значение, которым мы можем управлять ( в теории это будет выглядеть очень похоже на реальные данные, но для контекста этого вопроса я сделал его строкой * 1033) *). Затем мы проверяем, что getPoolJobs
возвращает значение, которое возвращает функция ElasticSearchService
getElasticSearchData
, так как это функциональность этой функции.
Это кажется довольно тривиальным в этом случае и может показаться бесполезным, но когда после внешнего вызова начинает действовать бизнес-логика, становится понятно, почему мы хотим издеваться. Скажем, у нас есть какое-то преобразование данных, чтобы сделать строку заглавной, прежде чем мы вернемся из getPoolJobs
метода
export class PoolJobService {
constructor(private readonly elasticSearchService: ElasticSearchService) {}
getPoolJobs(data: any): string {
const returnData = this.elasticSearchService.getElasticSearchData(data);
return returnData.toUpperCase();
}
}
Отсюда в тесте мы можем сказать getElasticSearchData
, что возвращать, и легко утверждать, что getPoolJobs
выполняет необходимую логику (утверждая, что строка действительно в верхнем регистре), не беспокоясь о логике внутри getElasticSearchData
или о создании каких-либо сетевые звонки. Для функции, которая ничего не делает, но возвращает выходные данные других функций, она чувствует немного как обман ваших тестов, но на самом деле это не так. Вы следуете шаблонам тестирования, используемым большинством других в сообществе.
Когда вы перейдете к тестам integration
и e2e
, вам понадобятся внешние выноски и убедитесь, что ваш поисковый запрос возвращает то, что вы ожидаете, но это выходит за рамки модульного тестирования.