[英]In Jest, how can I make a test fail?
我知道我可以從測試內部拋出一個錯誤,但我想知道是否有類似 Jasmine 提供的全局fail()
方法?
Jest 實際上使用了 Jasmine,所以你可以像以前一樣使用fail
。
示例調用:
fail('it should not reach here');
這是 Jest 的 TypeScript 聲明文件中的定義:
declare function fail(error?: any): never;
如果你知道某個特定的調用應該失敗,你可以使用expect
。
expect(() => functionExpectedToThrow(param1)).toThrow();
// or to test a specific error use
expect(() => functionExpectedToThrow(param1)).toThrowError();
有關傳入字符串、正則表達式或 Error 對象以測試toThrowError
方法中的預期錯誤的詳細信息,請參閱Jest 文檔。
對於異步調用,請使用.rejects
// returning the call
return expect(asyncFunctionExpectedToThrow(param1))
.rejects();
// or to specify the error message
// .rejects.toEqual('error message');
使用 async/await 您需要使用 async 標記測試功能
it('should fail when calling functionX', async () => {
await expect(asyncFunctionExpectedToThrow(param1))
.rejects();
// or to specify the error message
// .rejects.toEqual('error message');
}
另請注意,Jest 的未來版本中可能會刪除 Jasmine fail
功能,請參閱 Yohan Dahmani 的評論。 您可以開始使用上面的expect
方法,或者使用throw new Error('it should not reach here');
進行查找和替換fail
; 如其他答案所述。 如果你更喜歡fail
的簡潔性和可讀性,如果 Jasmine 從 Jest 中刪除,你總是可以創建自己的函數。
function fail(message) {
throw new Error(message);
}
你可以通過拋出錯誤來做到這一點。 例如:
test('Obi-Wan Kenobi', () => {
throw new Error('I have failed you, Anakin')
})
復制/意大利面失敗測試:
it('This test will fail', done => {
done.fail(new Error('This is the error'))
})
在某些情況下,某些答案將不起作用。 在async-await
的世界中,這樣的 try-catch 邏輯是很常見的。
try {
await someOperation();
} catch (error) {
expect(error.message).toBe('something');
}
現在想象一下,如果someOperation()
以某種方式通過了,但您預計它會失敗,那么這個測試仍然會通過,因為它從未進入 catch 塊。 所以我們想要的是確保如果 someOperation 沒有拋出錯誤則測試失敗。
所以現在讓我們看看哪些解決方案有效,哪些無效。
接受的答案在這里不起作用,因為拋出將再次被捕獲。
try {
await someOperation();
throw new Error('I have failed you, Anakin');
} catch (error) {
console.log('It came here, and so will pass!');
}
true === false 的答案也不起作用,因為斷言也會引發類似上面的錯誤,該錯誤將被捕獲。
try {
await someOperation();
expect(true).toBe(false); // This throws an error which will be catched.
} catch (error) {
console.log('It came here, and so will pass!');
}
對於這種情況,一種可行的解決方案(如@WhatWouldBeCool 的回答所示)如下。 現在它明確地沒有通過測試。
try {
await someOperation();
fail('It should not have come here!')
} catch (error) {
console.log('It never came here!');
}
Jest 不再正式支持fail()
函數。 相反,您可以做幾件事來明確地失敗。
您可以將您的 promise 函數包裝在 expect 中,並告訴 jest 該函數應該拒絕給定錯誤。 如果someOperation()
以某種方式通過,jest 將拋出錯誤。 如果someOperation()
因您指定之外的任何其他原因而失敗,它將引發錯誤。 除了toThrowError()
之外,您還可以使用其他不同的方法。
await expect(someOperation()).rejects.toThrowError('error!')
您可以在測試中明確聲明您期望的斷言數量。 如果由於someOperation()
從未失敗而不匹配,則 jest 將引發錯誤。
expect.assertions(1)
try {
await someOperation();
} catch (error) {
expect(error.message).toBe('something');
}
不要認為有,在這里討論: https ://github.com/facebook/jest/issues/2129
這里有很多好主意。 僅添加有關測試異步代碼的額外信息,這可能導致嘗試使 Jest 顯式失敗,請查看Testing Asynchronous Code
的文檔https://jestjs.io/docs/en/asynchronous
要測試一個返回解析的 Promise 的函數,返回 Promise 很重要,因此 Jest 知道只有在 Promise 解析或超時時才完成測試:
test('the data is peanut butter', () => {
return fetchData().then(data => {
expect(data).toBe('peanut butter')
})
})
要測試返回拒絕的 Promise 的函數,返回 Promise 很重要,因此 Jest 知道只有在 Promise 被拒絕或超時時才進行測試。 並且還必須說明 Jest 需要計算多少個斷言,否則如果 Promise 被解決,它就不會失敗——在這種情況下這是錯誤的——:
test('the fetch fails with an error', () => {
expect.assertions(1)
return fetchData().catch(e => expect(e).toMatch('some specific error'))
})
你總是可以做這樣的事情:)
expect(true).toBe(false);
添加 jest-fail-on-console npm 包,然后在您的 jest.config.js 上
import failOnConsole from 'jest-fail-on-console'
failOnConsole();
一旦由於測試項目中拋出錯誤或警告而由 jest 完成控制台錯誤或警告,這將導致測試失敗。
如果您將字符串傳遞給它,傳遞給每個測試的完成回調將引發錯誤。
例如
it('should error if the promise fails', async (done) => {
try {
const result = await randomFunction();
expect(result).toBe(true);
done();
} catch (e) {
done('it should not be able to get here');
}
});
在下面的代碼中,如果 randomFunction 拋出錯誤,它將被捕獲並自動失敗,因為字符串被傳遞給 done。
我剛遇到這個,經過一番挖掘,我找到了問題的根源。
Jest 自成立以來一直與 Jasmine 兼容。Jasmine 提供了fail
function 以編程方式使測試失敗。 這對於拋出錯誤會導致測試錯誤通過的情況非常有用(過度簡化的示例,但希望能說明用例):
function alwaysThrows() {
throw new Error();
}
describe('alwaysThrows', () => {
it('should throw', () => {
try {
alwaysThrows();
// here if there is nothing to force a failure, your
// test could "pass" as there are no failed expectations
// even though no error was thrown. If you just put the
// following to prevent that, you actually force the test
// to always pass:
throw new Error('it should have failed');
// that's why instead you use Jasmine's `fail(reason)` function:
fail('it should have failed');
} catch(err) {
expect(err).toBeDefined();
}
});
)
});
所以,發生的事情是這樣的:
fail()
function ,因為它的默認測試運行器是jest-jasmine2
,它提供了fail()
。jest-jasmine2
替換為jest-circus
作為默認測試運行器。 jest-circus
沒有實現fail()
function。這在 2021 年 7 月 28 日被報告為錯誤: https://github.com/facebook/jest/issues/11698fail()
function,所以自動完成和 TypeScript 編譯器仍然認為它存在並且可以使用。 DefinitelyTyped 中也存在一個問題: https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/55803這個線程的問題是他們決定不從類型定義中刪除它,因為它被標記為Jest 存儲庫中的“回歸”。 不幸的是,Jest 存儲庫的線程沒有關於他們將來是否支持這一點的官方回應,因此類型定義處於不確定狀態。 所以,長話短說,Jest 默認不支持fail()
fail()
但知道這是默認任務運行程序的問題,您可以通過告訴 Jest 使用jest-jasmine2
而不是默認jest-circus
賽跑者:
npm i -D jest-jasmine2
module.exports = { testRunner: "jest-jasmine2" };
PS:通常有比try
/ catch
更好的方法來解決實際測試用例中的錯誤。 您可以在此處查看在同步和異步上下文中不需要try
/ catch
的不同方式處理錯誤的示例: https://gist.github.com/joeskeen/d9c053b947e5e7462e8d978286311e83
您可以拋出一個模擬應用程序拋出的錯誤的錯誤,然后期望它的消息與實際不同。
try {
await somthingYouExpectToFail();
throw new Error("Fail!");
} catch (error) {
expect(error.message).not.toBe("Fail!");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.