如何测试自定义JavaScript Github actions?

3

我想创建一个JavaScript Github action,并使用Jest进行测试。根据文档,我开始解析输入,以下是示例代码。

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

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

在开发过程中运行此代码会引发以下错误:

需要输入但未提供:my-key

这是预期的,因为该代码未在Github操作环境中运行。但是,是否可以为此创建测试?例如:
describe('getMyKey', () => {
  it('throws if the input is not present.', () => {
    expect(() => getMyKey()).toThrow();
  });
});

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

5

有几种方法可以采取。

手动设置输入

将输入作为环境变量传递给操作,前缀为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的模拟功能

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

文档: ES6类模拟

抽象操作

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

此外,我不喜欢使用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函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接