【问题标题】:Unit test functions that use vscode extension api functions使用 vscode 扩展 api 函数的单元测试函数
【发布时间】:2018-06-03 00:33:17
【问题描述】:

我正在尝试找出一种对函数进行单元测试的方法,其中包括 vscode 扩展 api 中包含的帮助函数,例如 showQuickPick。示例用法:vscode.window.showQuickPick(['one', 'two']);

我一直在尝试对它们进行存根和模拟,但是虽然我不确定这是否是正确的方法,但无论如何我都没有运气。

一个完整的例子可能类似于:

logic.js

export async function unitTestMe(): Promise<string> {
  const quickPickAnswer: string = vscode.window.showQuickPick(['one', 'two']);
  return quickPickAnswer;
}

logic.test.js

import { unitTestMe } from './logic';
describe('should return user input', () => {
  test('', () => {
     const expected: string = 'expect me';
     const actual: string = await unitTestMe();
     expect(actual).to.eql(expected);
  })
})

【问题讨论】:

  • 你能解释一下当你存根或嘲笑 showQuickPick() 时“没有任何运气”是什么意思吗?您是否有错误,或者您只是担心您的解决方案可能是“难闻的代码”?
  • 好吧。我不知道如何模拟/存根 showQuickPick 作为 unitTestMe() 对 vscode 扩展 api 的内部调用,我认为这可能是问题所在。

标签: typescript unit-testing visual-studio-code mocha.js vscode-extensions


【解决方案1】:

解决您的问题的方法称为“依赖注入”:

首先,尝试将依赖项与代码分离,然后以一种可以从函数、类或原型外部设置这些依赖项的方式进行。

 function unitTestMe(vsCodeExtensionApi) {
    const quickPickAnswer = vsCodeExtensionApi.window.showQuickPick(['one', 'two']);
    return quickPickAnswer;
 }

或者如果你有课

class MagicClass {
   constructor(vsCodeExtensionApi) {
      this._vsCodeExtensionApi = vsCodeExtensionApi;
   }

   unitTestMe() {
       const quickPickAnswer = this._vsCodeExtensionApi.window.showQuickPick(['one', 'two']);
       return quickPickAnswer;
   }

现在您可以像这样将存根或模拟传递给 unitTestMe

const stub = {
   window : {
      showQuickPick = function(param) {
         // return some stuff
      }
   }
}

unitTestMe(stub)

【讨论】:

    【解决方案2】:

    这是我在当前项目中的做法:我创建了一个名为 VscodeEnvironment 的类,我在其中包装了 Vs Code API(间接层)

    export class VscodeEnvironment {
        public getActiveTextEditor(): vscode.TextEditor{
            return vscode.window.activeTextEditor;
        }
    
        public showErrorMessage(message: string): void {
            vscode.window.showErrorMessage(message);
        }
    
        public showQuickPick<T extends QuickPickItem>(items: T[] | Thenable<T[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<T | undefined> {
            return vscode.window.showQuickPick(items, options, token);
        }
    }
    

    在我的单元测试中,我设置了一个 VscodeEnvironment 存根来返回一个已解决的承诺:

    let vscodeEnvStub = moq.Mock.ofType(VscodeEnvironment);
    vscodeEnvStub.setup(x => x.showQuickPick(moq.It.isAny(), moq.It.isAny())).returns(()=>Promise.resolve<QuickPickItem>(fakeItem));
    

    我正在使用 typemoq,但在其他模拟框架中应该不会有太大不同

    【讨论】:

    • 第 1 部分:间接层解决了我的部分问题!但是,我需要从我的代码中删除以下函数:await commands.executeCommand('vscode.open', uri);,以便我可以使用 jest 对流进行单元测试,因为 vscode api 模拟如下:jest.mock('../../src/vscode/VscodeEnvironment', () =&gt; jest.fn()); 代码被重构为VscodeEnvironment:@ 987654326@
    • 第 2 部分:唯一的其他更改是使间接层成为单例:public static getInstance(): VscodeEnvironment { if (!VscodeEnvironment.instance) { VscodeEnvironment.instance = new VscodeEnvironment(); } return VscodeEnvironment.instance; } 当我尝试使用新流程调用 executeCommand 时会引发以下错误消息:> 没有扩展上下文
    【解决方案3】:

    如果您需要模拟showQuickPick 方法,下面的代码会这样做:

    vscode.window.showQuickPick = (items: string[] | Thenable<string[]>) => {
      return Promise.resolve('Continue') as Thenable<any>;
    };
    

    【讨论】:

      猜你喜欢
      • 2020-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多