如何测试自定义 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.mock
或 jest.spyOn
来模拟 getInput
的行为。
抽象动作
我不喜欢设置全局环境变量,因为一个测试可能会影响另一个测试,具体取决于它们在 运行 中的顺序。
此外,我不喜欢使用 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
函数。
我想创建一个 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.mock
或 jest.spyOn
来模拟 getInput
的行为。
抽象动作
我不喜欢设置全局环境变量,因为一个测试可能会影响另一个测试,具体取决于它们在 运行 中的顺序。
此外,我不喜欢使用 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
函数。