node.js - 在 Node js 中模拟 gcp pubsub 对象。 Jest

标签 node.js unit-testing google-cloud-platform jestjs

我正在尝试为 GCP 云功能编写单元测试。下面是我正在尝试测试的代码片段。

//index.js
const {PubSub} = require('@google-cloud/pubsub');
const pubsub = new PubSub();

exports.myFunction = functions.runWith(RUNTIME_OPTS).https.onCall(async (data, context) => {
  //pubsubbody = generated..

  //some logic

  await pubsub.topic(topicname).publish(pubsubBody, {
    platform: body.platform,
    environment: body.environment,
    event: !!event ? event : 'unknown',
  });
});

我能够使用 firebase-functions-test 库测试 myFunction 逻辑。 我做了这样的事情

//test.js
const fft = require('firebase-functions-test')();
const funcs = require('../../index');

describe('function to test viewAddRequestedProxy', () => {
  const wrapped = fft.wrap(funcs.viewAddRequestedProxy);

  // simple logic test.
  test('NullDataTest', async () => {
    const result = await wrapped(null, null);
    expect(result).toStrictEqual({output: 'xyz'});
  });
});

现在我想测试在函数内进行 pubsub 调用的行。 我尝试了很多东西,但我对 Node.js 以及一般的模拟对象都很陌生。

我不明白如何模拟 index.js 中的 pubsub 对象并检查它是否正在发布消息。

await pubsub.topic(topicname).publish(pubsubBody, {
  platform: body.platform,
  environment: body.environment,
  event: !!event ? event : 'unknown',
});

我很困惑是否需要导出我的 pubsub 对象并访问它 test.js 。我尝试了这个,但由于某种原因 "module.exports = { pubsub: pubsub };" 对我不起作用。 我还尝试使用spyOn 在 test.js 中创建模拟

const {PubSub} = require('@google-cloud/pubsub');
const singleAdd = (PubSub) => {
  PubSub.topic;
};

test('spyOn .toBeCalled()', (object, method) => {
  const somethingSpy = jest.spyOn(PubSub, 'topic');
  somethingSpy();
  const topic = PubSub.topic('abc');
  expect(somethingSpy).toBeCalled();
});

还尝试了手动模拟,尽管我不确定是否需要这个。通过创建一个 Mocks 文件夹,但似乎没有任何效果。

任何帮助将不胜感激。我想我完全偏离了轨道。

最佳答案

为了模拟 Node 库,您需要在 __mocks__/lib-name/index.js 中放置一个文件,该文件将模仿真实界面

就您而言,请将 pubsub.js 文件放入 __mocks__/@google-cloud/ 中。

//pubsub.js

class PubSubMock {
  static mockInstances = [];

  static clearAllMocks() {
    PubSubMock.mockInstances.forEach((instance) =>
      Object.getOwnPropertyNames(
        instance.constructor.prototype
      ).forEach((method) => method.mockClear())
    );
    
    PubSubMock.mockInstances.length = 0;
  }

  constructor() {
    Object.getOwnPropertyNames(this.constructor.prototype).forEach((method) => {
      spyOn(this, method).and.callThrough();
    });

    PubSubMock.mockInstances.push(this);
  }

  topic(topic) {
    // you can implement here the logic
    return this;
  }

  publish(body, obj) {
    return this;
  }
}

module.exports.PubSub = PubSubMock;

Jest 将确保'@go​​ogle-cloud/pubsub' 的每个需求都映射到该模拟文件。

PubSub 类的模拟实现会自动监视所有类方法,这样您就可以测试是否调用了某个方法以及使用什么参数。

问题是您的生产代码创建了 PubSub 的新实例,但没有公开它,因此您无法获取它的引用。一个小技巧是公开一个静态属性,该属性将保存所有创建的实例,并将由 PubSub.mockInstances 公开。

const {PubSub} = require('@google-cloud/pubsub');
const funcs = require('../../index');

test('spyOn .toBeCalled()', (object, method) => {
  funcs() // call for you real code
  const mockInstance = PubSub.mockInstances[0];
  expect(mockInstance.topic).toHaveBeenCalledWith('arg1');
});

关于node.js - 在 Node js 中模拟 gcp pubsub 对象。 Jest ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63044403/

相关文章:

javascript - 在其他地方初始化 ('mymodule' 后调用 require 'mymodule' ) 是否正确?

javascript - Node.js url 方法返回 null

c# - UnitTests - Moq - 如何从与 Setup() 中的参数匹配的 Moq 中返回 () 对象

hadoop - Drop Hive Table和MSCK修复失败,表存储在Google云存储桶中

java - 在 App Engine Devserver Servlet 中查看替换字符

javascript - Angular html 文件找不到 JS Controller [Node.js/Angular]

node.js - Typescript+Node.js 中的 os.EOL

ruby-on-rails - 模拟外部 API

c# - 我正在尝试用 C# 为静态方法编写单元测试

firebase - 将 Google Firebase Firestore 与 ChatGPT API 集成