我在Ember測試中發現了一些不明確的錯誤消息,沒有有用的堆棧跟蹤或任何其他信息來找出潛在的原因,但是這種情況需要獎品作爲其中最隱晦的就是這些。Ember無法在對象銷燬後調用writableChainWatchers
我有這樣的灰燼應用,在那裏測試是在一個非常奇怪的方式失敗:
$ ember test -m "Acceptance | main report" 1 ↵
cleaning up...
Built project successfully. Stored in "/home/username/work/my-project/frontend/tmp/core_object-tests_dist-HinFNKHW.tmp".
ok 1 PhantomJS 2.1 - Acceptance | main report: visiting main home
not ok 2 PhantomJS 2.1 - Acceptance | main report: it changes structure
---
actual: >
false
expected: >
true
stack: >
[email protected]://localhost:7357/!/assets/test-support.js:7199:49
[email protected]://localhost:7357/!/assets/js/vendor.js:54101:22
[email protected]://localhost:7357/!/assets/js/vendor.js:32467:23
[email protected]://localhost:7357/!/assets/js/vendor.js:46036:32
[email protected]://localhost:7357/!/assets/js/vendor.js:73035:19
http://localhost:7357/!/assets/js/vendor.js:73935:28
[email protected]://localhost:7357/!/assets/js/vendor.js:15192:18
[email protected]://localhost:7357/!/assets/js/vendor.js:15260:15
[email protected]://localhost:7357/!/assets/js/vendor.js:15384:20
[email protected]://localhost:7357/!/assets/js/vendor.js:15454:28
[email protected]://localhost:7357/!/assets/js/vendor.js:15577:19
http://localhost:7357/!/assets/js/vendor.js:15873:29
message: >
Error: Assertion Failed: Cannot call writableChainWatchers after the object is destroyed.
Log: |
...
1..2
# tests 2
# pass 1
# skip 0
# fail 1
Not all tests passed.
Error: Not all tests passed.
at EventEmitter.App.getExitCode (/home/username/work/my-project/frontend/node_modules/testem/lib/app.js:434:15)
at EventEmitter.App.exit (/home/username/work/my-project/frontend/node_modules/testem/lib/app.js:189:23)
at /home/username/work/my-project/frontend/node_modules/testem/lib/app.js:103:14
at tryCatcher (/home/username/work/my-project/frontend/node_modules/testem/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/username/work/my-project/frontend/node_modules/testem/node_modules/bluebird/js/release/promise.js:510:31)
at Promise._settlePromise (/home/username/work/my-project/frontend/node_modules/testem/node_modules/bluebird/js/release/promise.js:567:18)
at Promise._settlePromise0 (/home/username/work/my-project/frontend/node_modules/testem/node_modules/bluebird/js/release/promise.js:612:10)
at Promise._settlePromises (/home/username/work/my-project/frontend/node_modules/testem/node_modules/bluebird/js/release/promise.js:691:18)
at Async._drainQueue (/home/username/work/my-project/frontend/node_modules/testem/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/home/username/work/my-project/frontend/node_modules/testem/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues [as _onImmediate] (/home/username/work/my-project/frontend/node_modules/testem/node_modules/bluebird/js/release/async.js:17:14)
at processImmediate [as _immediateCallback] (timers.js:383:17)
注意的錯誤消息:
Cannot call writableChainWatchers after the object is destroyed.
我的第一個問題是,我怎麼能弄清楚什麼是導致這個奇怪的錯誤,當我得到的堆棧跟蹤是什麼,但有幫助。這不僅不利於獲得構建的vendor.js
的這些瘋狂行數,而且堆棧跟蹤中也沒有任何內容來自我的應用程序本身。所以沒有線號可以幫助我。
另外,在dev或生產環境中運行應用程序時,不會發生此錯誤情況。 這只是在測試環境中發生。
最後,也許更重要的是:我意識到錯誤的原因與狀態從一個測試泄漏到另一個測試有關。在該測試文件中,您可以看到有兩個測試。第一個通過,但第二個失敗。當我評論第一個時,爲了專注於唯一失敗的測試,事實證明它不會失敗。當我在文件中交換這兩個測試的順序時,那麼失敗的那個,以前是次要的,現在它是第一個沒有失敗的測試。相反,當它是第一個時,它正在通過,現在是最後一次失敗。
更新
我有關於發生此錯誤的條件的更多信息。
我在應用程序中精確定位了代碼行,並在測試中引發了這一行。它看起來像這樣:
Ember.run(() => this.set('value', value));
這行代碼是在我的應用程序使用compute
方法內。這位助手的觀察員在服務中的某些屬性更改其值時調用this.recompute()
。很像是顯示here。
引發此錯誤的實際代碼不是this.set
調用。我刪除它,代碼仍然會發生。這僅僅是Ember.run
的罪魁禍首。但是,當我直接調用this.set
而未將其包裝在Ember.run
中時,也會發生該錯誤。爲了完全清楚,任何以下三行代碼的提出同樣的錯誤:
Ember.run(() => this.set('value', value));
Ember.run(() => {});
this.set('value', value);
我必須馬上修復它是包裝一個try/catch
內符合空catch
塊,默默的唯一途徑忽略錯誤。
我還追蹤了引起這個錯誤的ember.js中的代碼行。你可以看看它here。我仍然希望有人能夠弄清楚這一點。
感謝AlexMA。我會更深入地探討你提到的這個附加組件。我知道你在第一段中提到的這個問題,但是在這種情況下並不完全相同,原因有兩個:首先,當它是在一個被破壞的對象中設置值時,錯誤將會像「yo called」集合'在一個被毀壞的物體上「。但是這個「可寫的觀察者」事物使得它更加怪異和低層次。其次,無論事情發展得有多快,一些國家從一次測試漏到另一次測試是不可接受的。如果測試通過隔離運行時,它應該在套件中運行時通過。 – Ernesto
我在上面添加了更多相關信息,以防情況下對診斷這種情況有用。 – Ernesto
如果您嘗試在'if(!this.isDestroyed){...}'中包裝代碼,該怎麼辦?或者試着在那裏包裝'recompute'電話?在這一點上,我有點超出我的深度,並會在我的開發控制檯中打開「暫停捕捉異常」,或嘗試在Ember鬆弛通道中找到一些幫助。 – AlexMA