Testrpc
預期會引發錯誤的松露測試承諾
我與檢查輸入參數的方法簽訂了契約,
require(bool)
因此如果至少有一個條件不匹配,則會引發錯誤。在測試過程中(使用 Truffle 和 Chaijs),它看起來像:Error: VM Exception while processing transaction: invalid opcode at Object.InvalidResponse (/usr/lib/node_modules/truffle/build/cli.bundled.js:37022:16) at /usr/lib/node_modules/truffle/build/cli.bundled.js:210096:36 at XMLHttpRequest.request.onreadystatechange (/usr/lib/node_modules/truffle/build/cli.bundled.js:208875:13) at XMLHttpRequestEventTarget.dispatchEvent (/usr/lib/node_modules/truffle/build/cli.bundled.js:210748:18) at XMLHttpRequest._setReadyState (/usr/lib/node_modules/truffle/build/cli.bundled.js:211038:12) at XMLHttpRequest._onHttpResponseEnd (/usr/lib/node_modules/truffle/build/cli.bundled.js:211193:12) at IncomingMessage.<anonymous> (/usr/lib/node_modules/truffle/build/cli.bundled.js:211153:24) at endReadableNT (_stream_readable.js:1047:12) at _combinedTickCallback (internal/process/next_tick.js:102:11) at process._tickCallback (internal/process/next_tick.js:161:9)
測試使用這樣的承諾:
return MyToken.deployed().then(inst => { instance = inst; return instance.purchase({from: accounts[1], value: amount}); })....
問題是我無法處理這個異常。我試圖將
purchase
呼叫包裝到函式中並使用assert.throws(executor, message)
- 它不起作用(假設由於它需要同步的東西)。如何測試這個承諾(最好不添加
chai-as-promised
)?
~~在進一步處理之前,您可以
catch
在被拒絕時做出承諾。~~Catch 在範例中不起作用,因為它不僅會擷取事務失敗,還會擷取任何其他錯誤。您可以使用第二個參數來
then
擷取在進一步處理之前被拒絕的承諾,即MyPromise.then(() => { /* check when succeed */ }, () => { /* check when failure */ })
contract('MyToken', (accounts) => { it("Should fail", () => { return MyToken.deployed().then((instance) => { return instance.purchase({ from: accounts[1], value: amount }); }).then(() => { assert.ok(false, "It didn't fail"); }, () => { assert.ok(true, "Passed"); }); }); });
Promise 不會拋出,這就是
assert.throws
失敗的原因。Byzantium 之後的注意事項:另外我應該提到,在 Byzantium 分叉之後,以前生成 throw 的一些操作將不再做這樣的事情。檢查這篇文章,以便您可以針對該事實更新您的測試:由於 REVERT 操作碼不消耗所有氣體,如何在拜占庭分叉後檢測失敗的交易?
也許更好的方法是使用 async/await 和
assert.throws
.訣竅是將承諾轉換為
assert.throws
可以報告的非非同步內容。第一個輔助函式async function verifyThrows(pred, message) { let e; try { await pred(); } catch (ex) { e = ex; } assert.throws(() => { if (e) { throw e; } }, message); }
我們可以使用輔助函式在函式中傳遞承諾執行
contract('MyToken', (accounts) => { it("Should fail", async () => { const instance = await MyToken.deployed(); await verifyThrows(() => { instance.purchase({ from: accounts[1], value: amount }); }, /revert/); }) });