Как смоделировать реализацию функции, вызываемой тестируемой службой? - PullRequest
0 голосов
/ 24 октября 2019

У меня есть проект NestJS, над которым я работаю, и мне нужно написать модульные тесты моих сервисов.

У меня есть служба BigQueryService, которая использует @ google-cloud / bigquery для доступа к набору данных Big Query и выполнения запроса. У меня также есть другой сервис (назовем его MyService), задача которого - построить запрос, который мне нужен, в зависимости от какой-то другой логики, и передать его в BigQueryService, получить от него результат запроса и вернуть его контроллеру, который будет ввключите отправку данных через конечную точку.

Мне нужно написать модульные тесты для MyService, и для этого мне нужно смоделировать BigQueryService таким образом, чтобы он не требовал разрешения зависимостей BigQueryService. Вот мой код:

bigquery.service.ts:

import { Injectable } from '@nestjs/common';
import { BigQuery } from '@google-cloud/bigquery';
...
@Injectable()
export class BigqueryService {
  ...
  constructor(
    ...
  ) {
    ...
  }

  async executeQuery(querySentence: string): Promise<Array<any>> {
    ...
    return response;
  }
}

MyService.service.ts:

import { Injectable } from '@nestjs/common';
import { BigqueryService } from '../bigquery/bigquery.service';
//the following is just a service that helps log the results of this service
import { MyLogger } from '../../config-service/logger.service';
...
@Injectable()
export class MyService {
  constructor(
    private readonly bigqueryService: BigqueryService,
    private readonly logger: MyLogger,
  ) { }
  ...
  async myFunc(request: RequestInterface): Promise<Array<ResponseInterface>> {
    let query = (some code to create a query i want)
    return await this.bigqueryService.executeQuery(query);
  }

Для тестов я следовал за ответамив этой ветке: Макет метода сервиса, вызываемого тестируемым при использовании Jest

jest.mock('../services/bigquery/bigquery.service', () => jest.fn()) 
const bq = require('../services/bigquery/bigquery.service')
jest.mock('../config-service/logger.service', () => jest.fn())
const ml = require('../config-service/logger.service')

const executeQuery = jest.fn()
executeQuery.mockReturnValue('desired value')
bq.mockImplementation(() => ({executeQuery}))


describe("Testing consumption moment service function", () => {

  it("should call the mock service", () => {
    const ms = new MyService(bq,ml)
    ms.myFunc(requestBody) //requestBody is a RequestInterface
    expect(bq.executeQuery).toHaveBeenCalled
    expect(bq.executeQuery).toHaveReturned
 });
});

Этот тест пройден, поэтому я предполагаю, что правильно издевался над сервисом bigquery. Но когда я пытаюсь утверждать, что возвращаемое значение является правильным, я делаю тест асинхронным, чтобы тест не завершился, пока myFunc фактически не завершится, и у меня может быть результат для сравнения.

 it("should call the mock service", async () => {
   const ms = new MyService(bq,ml) 
   await ms.myFunc(requestBody)
   expect(bq.executeQuery).toHaveBeenCalled
   expect(bq.executeQuery).toHaveReturned
 });

Это приводит к ошибке: Ошибка типа: this.bigqueryService.executeQuery не является функцией Ошибка указывает на строку, где myFunc вызывает this.bigqueryService.executeQuery.

Я пробовал разные примеры насмешек, чтобы можно было смоделировать вызов этой функции, но ни один из них не подошел так близко, как в примере выше. Я также пытался использовать

jest.spyOn(bq, 'executeQuery') 

Но это также сказало, что executeQuery не был функцией: Невозможно следить за свойством executeQuery, поскольку оно не является функцией;вместо этого дано неопределенное значение

Может ли кто-нибудь указать мне правильное направление здесь? Что-то мне не хватает, чтобы этот тест работал? Я заранее благодарю всех за любую помощь, которую вы можете оказать мне.

Ответы [ 2 ]

1 голос
/ 25 октября 2019

Я все понял, поэтому, если кто-то находится в такой же ситуации, вот где я нашел ответ: https://jestjs.io/docs/en/jest-object

Тест был исправлен так:

jest.mock('../config-service/logger.service', () => jest.fn())
const ml = require('../config-service/logger.service')
const executeQuery = jest.fn()

describe("Testing service function", () => {

  it("should call the mock service", async () => {
    jest.mock('../services/bigquery/bigquery.service', () => {
      return {
        executeQuery: jest.fn(() => 'desired output'),
      };
    })
    const bq = require('../services/bigquery/bigquery.service')

    const ms = new MyService(bq,ml)
    const p = await ms.myFunc(requestBody) //requestBody is a RequestInterface
    expect(bq.executeQuery).toHaveBeenCalled
    expect(bq.executeQuery).toHaveReturned
    expect(p).toEqual(desired result)
 });
});
0 голосов
/ 24 октября 2019
bq.mockImplementation(() => ({executeQuery}))

Не асинхронно, попробуйте вернуть обещание

bq.mockImplementation(() => (Promise.resolve({executeQuery})))
...