【问题标题】:How to mock implementation of a function called by a service being tested?如何模拟被测试服务调用的函数的实现?
【发布时间】:2020-02-21 03:13:16
【问题描述】:

我正在处理一个 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);
  }

对于测试,我遵循了这个帖子中的答案:Mock a method of a service called by the tested one when using 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
 });

出现错误:TypeError: this.bigqueryService.executeQuery is not a function 错误指向 myFunc 调用 this.bigqueryService.executeQuery 的行。

我尝试了不同的模拟示例,以便可以模拟对该函数的调用,但没有一个像上面的示例那样接近。我也尝试过使用

jest.spyOn(bq, 'executeQuery') 

但这也说明executeQuery 不是函数:不能窥探executeQuery 属性,因为它不是函数;改为未定义

有人可以在这里指出正确的方向吗?我是否缺少一些东西来使这个测试工作?我提前感谢大家给我的任何帮助。

【问题讨论】:

    标签: javascript typescript jestjs nestjs


    【解决方案1】:

    我最终弄明白了,所以如果有人遇到同样的情况,我在这里找到了答案: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)
     });
    });
    

    【讨论】:

      【解决方案2】:
      bq.mockImplementation(() => ({executeQuery}))
      

      不是异步的,试试返回一个promise

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

      【讨论】:

      • 我进行了您建议的更改,但错误 TypeError: this.bigqueryService.executeQuery is not a function 仍然存在。
      • jest.spyOn(bq, 'executeQuery').mockImplementation(() =&gt; ...)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-20
      • 2020-01-20
      • 1970-01-01
      • 2021-01-01
      • 1970-01-01
      • 2019-11-18
      • 1970-01-01
      相关资源
      最近更新 更多