如何测试自定义 JavaScript Github 操作?

How to test custom JavaScript Github actions?

我想创建一个 JavaScript Github 动作并使用 Jest 进行测试。基于the docs我开始解析输入,给定下面的示例代码

import { getInput } from '@actions/core';

const myActionInput = getInput('my-key', { required: true });

运行 此代码在开发过程中抛出以下错误

Input required and not supplied: my-key

符合预期,因为代码不在 运行 内 Github 操作环境。但是是否可以为此创建测试?例如

describe('getMyKey', () => {
  it('throws if the input is not present.', () => {
    expect(() => getMyKey()).toThrow();
  });
});

如何使用上下文“伪造”/模拟这样的环境以确保我的代码按预期工作?

您可以采用多种方法。

手动设置输入

输入作为带有前缀 INPUT_ 且大写的环境变量传递给操作。了解这一点,您可以在 运行测试之前设置相应的环境变量。

在您的情况下,输入 my-key 需要作为名为 INPUT_MY-KEY.

的环境变量存在

这应该能让您的代码正常工作:

describe('getMyKey', () => {
  it('throws if the input is not present.', () => {
    process.env['INPUT_MY-KEY'] = 'my-value';
    expect(() => getMyKey()).toThrow();
  });
});

使用 Jest 的 Mocking

您可以使用 jest.mockjest.spyOn 来模拟 getInput 的行为。

文档:ES6 Class Mocks

抽象动作

我不喜欢设置全局环境变量,因为一个测试可能会影响另一个测试,具体取决于它们在 运行 中的顺序。

此外,我不喜欢使用 jest.mock 进行模拟,因为它感觉很神奇,而且我通常会花太多时间让它做我想做的事。问题很难诊断。

似乎通过多一点代码带来所有好处的是将操作拆分为一个函数,可以通过传入“全局”对象来调用该函数,例如 core.

// index.js
import core from '@actions/core';

action(core);

// action.js
function action(core) {
   const myActionInput = core.getInput('my-key', { required: true });
}

这使您可以像这样很好地测试您的操作:

// action.js
describe('getMyKey', () => {
  it('gets required key from input', () => {
    const core = {
      getInput: jest.fn().mockReturnValueOnce('my-value')
    };
    action(core);
    
    expect(core.getInput).toHaveBeenCalledWith('my-key', { required: true });
  });
});

现在你可以说我们不再测试如果输入不存在操作是否抛出错误,但也要考虑你在那里真正测试的是什么:你正在测试核心操作是否抛出错误如果输入缺失则出错。在我看来,这不是您自己的代码,因此值得测试。您只想确保根据合同(即文档)正确调用 getInput 函数。