当前位置: 代码迷 >> JavaScript >> 如何在javascript中实现基本单元测试以实现天蓝色的持久功能编排
  详细解决方案

如何在javascript中实现基本单元测试以实现天蓝色的持久功能编排

热度:86   发布时间:2023-06-05 11:37:47.0

什么是单元测试,它将伪造下面的协调器中对callActivity的调用以返回一个已知值并期望该协调器返回该值。

用于单元测试的azure持久函数文档中的示例[1]都是用C#编写的,尽管有几次尝试,但我无法用javascript复制它们。 这是因为我不知道如何使用伪造的上下文来构造协调器。

  const df = require('durable-functions');

  module.exports = df.orchestrator(function* orchestratorFunctionGenerator(context) {
    const input = context.df.getInput();
    const apimApiName = input.apimApiName;
    const indexNames = yield context.df.callActivity('GetIndexNames', apimApiName);
    const indexerName = indexNames.idle;
    const indexerStatus = yield context.df.callActivity('GetIndexerStatus', indexerName);
    return indexerStatus;
  });

[1]

我们采用的方法是将generator方法提取到其自己的模块中。

module.exports = function* orchestratorFunctionGenerator(context) {
  const input = context.df.getInput();
  const apimApiName = input.apimApiName;
  const indexNames = yield context.df.callActivity('GetIndexNames', apimApiName);
  const indexerName = indexNames.idle;
  const indexerStatus = yield context.df.callActivity('GetIndexerStatus', indexerName);
  return indexerStatus;
};

然后要求

const df = require('durable-functions');
const generatorFunction = require('./generator-function');

module.exports = df.orchestrator(generatorFunction);

然后隔离测试功能

const chai = require('chai');
const sinon = require('sinon');
const getIndexerStatusOrchestratorGenerator = require('../../GetIndexerStatusOrchestrator/generator-function');

const expect = chai.expect;

function iterateGenerator(generator) {
  let result = generator.next();
  while (!result.done) {
    result = generator.next(result.value);
  }
  return result;
}

describe('getIndexerStatusOrchestrator', () => {
  it('happy path should return \'inProgress\'', () => {
    const indexNames = { active: 'index-1', idle: 'index-2' };
    const apimApiName = 'api';
    const input = { apimApiName };
    const stubCallActivity = sinon.stub();
    stubCallActivity.withArgs('GetIndexNames', apimApiName).returns(indexNames);
    stubCallActivity.withArgs('GetIndexerStatus', indexNames.idle).returns('inProgress');

    const context = {
      df: {
        callActivity: stubCallActivity,
        getInput: sinon.fake.returns(input),
      },
    };

    const generator = getIndexerStatusOrchestratorGenerator(context);

    const result = iterateGenerator(generator);
    expect(result.value).to.equal('inProgress');
  });
  it('indexer status should be for the idle index', () => {
    const indexNames = { active: 'index-1', idle: 'index-2' };
    const apimIndexName = 'api';
    const input = { apimApiName: apimIndexName };
    const stubCallActivity = sinon.stub();
    stubCallActivity.withArgs('GetIndexNames', apimIndexName).returns(indexNames);
    stubCallActivity.withArgs('GetIndexerStatus', indexNames.idle);
    // use stub as a mock since we need both stub and mock behaviour
    // for 'callActivity' and this was the easier option
    stubCallActivity.withArgs('GetIndexerStatus').callsFake((method, indexerName) => {
      expect.fail(`Unexpected indexer name ${indexerName}`);
    });

    const context = {
      df: {
        callActivity: stubCallActivity,
        getInput: sinon.fake.returns(input),
      },
    };

    const generator = getIndexerStatusOrchestratorGenerator(context);

    iterateGenerator(generator);

    // expectations set above
  });
});

可以预料,这是编排器的一个简单例子。 我们的编排器中包含更多逻辑,并且测试将具有更大价值。

另外,我个人不会在第二次测试中使用模拟方法,而只会依靠使用存根来测试输出来伪造依赖项交互。

  相关解决方案