我是TypeScript / JavaScript的新手,但我有一个工作的VScode扩展,我很满意。我的问题是我的Mocha测试。我有以下功能
export async function getPackInfo (): Promise<IPackInfo> {
let validChars = '^[0-9a-zA-Z-]+$'
let ref
ref = await getInput('Pack Reference (lowercase and (-) only)', 'pack-reference', 'my-first-pack')
if (!ref.match(validChars)) {
vscode.window.showErrorMessage('Pack name can only contain letters, numbers and dashes', 'Got it')
return Promise.reject(new Error('Pack name can only contain letters, numbers and dashes. Pack will not be created correctly.'))
}
console.log(ref)
let packname = ref.replace(/-/g, ' ').toLowerCase()
.split(' ')
.map((s) => s.charAt(0).toUpperCase() + s.substring(1))
.join(' ')
console.log(packname)
let author
if (getSetting('defaultAuthor')) {
console.log('Got setting')
author = getSetting('defaultAuthor')
} else {
console.log('Need input')
author = await getInput('Pack Author', 'Pack Author', 'John Doe')
}
console.log(author)
let email
if (getSetting('defaultEmail')) {
email = getSetting('defaultEmail')
} else {
email = await getInput('Author Email', 'Author Email', '[email protected]')
}
console.log(email)
if (!author || !email) {
throw new Error('Pack author or email not defined')
}
// Write Pack Config File
let data: IPackInfo = {
'ref': ref,
'packname': packname,
'author': author,
'email': email
}
return data
}
这个函数调用另一个名为getInput的函数调用vscode.window.showInputBox:
export async function getInput (prompt: string, placeholder: string, defaultValue: string): Promise<string> {
let value = await vscode.window.showInputBox({ prompt: prompt, placeHolder: placeholder, value: defaultValue }).then(function(value) {
if (value) {
resolve(value)
}
throw new Error('No value for prompt')
})
我试图测试数据在'getPackInfo'函数中正确返回。我的测试目前看起来像这样:
it('Check that packname is converted correctly', function (done) {
let mockGetInput
mockGetInput = sinon.stub(vscode.window, 'showInputBox')
mockGetInput.onFirstCall().resolves('ref-pack-here')
mockGetInput.onSecondCall().resolves('Test Author')
mockGetInput.onThirdCall().resolves('[email protected]')
getPackInfo().then((res) => {
let output = res['ref']
console.log(`Output: ${res['packname']}`)
console.log(`Output: ${res['author']}`)
console.log(`Output: ${res['email']}`)
console.log(`Output: ${res['ref']}`)
}).catch(error => {
console.log(error)
})
done()
mockGetInput.restore()
})
我现在已经在这几天,但我无法让每个电话成为不同的价值!
第一个调用正确返回,但所有后续调用都不返回任何内容。
如果有更好的方法,我很乐意尝试!
看起来您需要对async
代码进行一些修复。
现在getInput
总是解决undefined
。 resolve
在then
条款中未定义,因此Promise
总是拒绝错误,但即使该问题不存在,否则将从value
返回的vscode.window.showInputBox
永远不会返回。
您可以通过将其更改为此问题来解决这些问题:
export async function getInput (prompt: string, placeholder: string, defaultValue: string): Promise<string> {
const value = await vscode.window.showInputBox({ prompt: prompt, placeHolder: placeholder, value: defaultValue });
if (value) {
return value;
}
throw new Error('No value for prompt')
}
你正确地创建了模拟,你只需要等待Promise
返回的getPackInfo
来解决,然后恢复模拟并结束测试。
现在它正在调用getPackInfo
,然后立即调用done
,恢复模拟,并在async
中的任何getPackInfo
代码甚至有机会运行之前结束测试。
解决这个问题的最简单方法是使用async
测试函数并在await
上调用Promise
:
it('Check that packname is converted correctly', async () => { // async test function
let mockGetInput;
mockGetInput = sinon.stub(vscode.window, 'showInputBox');
mockGetInput.onFirstCall().resolves('ref-pack-here');
mockGetInput.onSecondCall().resolves('Test Author');
mockGetInput.onThirdCall().resolves('[email protected]');
const res = await getPackInfo(); // await the Promise
console.log(`Output: ${res['packname']}`);
console.log(`Output: ${res['author']}`);
console.log(`Output: ${res['email']}`);
console.log(`Output: ${res['ref']}`);
mockGetInput.restore();
});