问题
I am trying to figure out a way to unit test functions, which include helper functions included in the vscode extension api, such as showQuickPick. Example usage: vscode.window.showQuickPick(['one', 'two']);
.
I have been trying to stub and mock those, but while I am not sure if that's even the right way to go, I haven't had any luck with it anyway.
A complete example could look something like:
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);
})
})
回答1:
The solution to your problem is called "dependency injection":
At first, try to separate dependencies from your code and then do it in a way that you can set these dependendies from outside of your function or class or prototype.
i.e.
function unitTestMe(vsCodeExtensionApi) {
const quickPickAnswer = vsCodeExtensionApi.window.showQuickPick(['one', 'two']);
return quickPickAnswer;
}
or if you have a class
class MagicClass {
constructor(vsCodeExtensionApi) {
this._vsCodeExtensionApi = vsCodeExtensionApi;
}
unitTestMe() {
const quickPickAnswer = this._vsCodeExtensionApi.window.showQuickPick(['one', 'two']);
return quickPickAnswer;
}
Now you can pass a stub or mock to unitTestMe like
const stub = {
window : {
showQuickPick = function(param) {
// return some stuff
}
}
}
unitTestMe(stub)
回答2:
Here is how I did it in my current project: I created a class called VscodeEnvironment where I wrapped Vs Code API (A layer of indirection)
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);
}
}
In my unit tests, I set up a VscodeEnvironment stub to return a resolved promise:
let vscodeEnvStub = moq.Mock.ofType(VscodeEnvironment);
vscodeEnvStub.setup(x => x.showQuickPick(moq.It.isAny(), moq.It.isAny())).returns(()=>Promise.resolve<QuickPickItem>(fakeItem));
I'm using typemoq, but it should not be very different in other mocking frameworks
回答3:
If you need to mock the showQuickPick
method, the following code will do so:
vscode.window.showQuickPick = (items: string[] | Thenable<string[]>) => {
return Promise.resolve('Continue') as Thenable<any>;
};
来源:https://stackoverflow.com/questions/47906194/unit-test-functions-that-use-vscode-extension-api-functions