2012-01-26 30 views
12

Tôi muốn kiểm tra rằng các chức năng sau đây thực hiện như mong đợi:Làm thế nào tôi có thể kiểm tra các lỗi không xác định trong mocha?

function throwNextTick(error) { 
    process.nextTick(function() { 
     throw error; 
    }); 
} 

Đây là nỗ lực của tôi:

describe("throwNextTick", function() { 
    it("works as expected", function (next) { 
     var error = new Error("boo!"); 
     var recordedError = null; 
     process.once("uncaughtException", function (error) { 
      recordedError = error; 
     }); 

     throwNextTick(error); 

     process.nextTick(function() { 
      recordedError.should.be(error); 
      next(); 
     }); 
    }); 
}); 

Nhưng mocha dường như muốn giữ lại bất kỳ lỗi nào cho chính nó, và không thử nghiệm của tôi khi nhận được chúng:

C:\Users\ddenicola\Programming (Synced)\pubit>mocha test/basicTest.js 

    throwNextTick 
    0) works as expected 

    ? 1 of 1 tests failed: 

    1) throwNextTick works as expected: 
    Error: boo! 
     at Test.fn (C:\Users\ddenicola\Programming (Synced)\pubit\test\basicTest.js:11:21) 
     at Test.run (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runnable.js:144:15) 
     at Runner.runTest (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:271:10) 
     at C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:315:12 
     at next (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:199:14) 
     at C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:208:7 
     at next (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:157:23) 
     at Array.0 (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:176:5) 
     at EventEmitter._tickCallback (node.js:192:40) 

Bất kỳ ý tưởng nào?

Trả lời

27

Cập nhật: Courtesy of casey-nuôi trong một chú thích bên dưới:

Tính đến nút v6.0.0 bạn có thể sử dụng process.prependOnceListener('uncaughtException', ...) để làm điều này nhiều hơn nữa một cách ngắn gọn.


Cũ câu trả lời:

Bí mật nằm trong process.listeners ('uncaughtException'):

http://nodejs.org/docs/latest/api/events.html#emitter.listeners

Đơn giản chỉ cần loại bỏ các listener mocha, thêm riêng của bạn, sau đó lắp lại người nghe mocha.

Xem dưới đây:

var assert = require('assert') 

function throwNextTick(error) { 
    process.nextTick(function() { 
     throw error 
    }) 
} 


describe("throwNextTick", function() { 
    it("works as expected", function (next) { 
     var error = new Error("boo!") 
     var recordedError = null 
     var originalException = process.listeners('uncaughtException').pop() 
     //Needed in node 0.10.5+ 
     process.removeListener('uncaughtException', originalException); 
     process.once("uncaughtException", function (error) { 
      recordedError = error 
     }) 
     throwNextTick(error); 
     process.nextTick(function() { 
      process.listeners('uncaughtException').push(originalException) 
      assert.equal(recordedError, error) 
      next() 
     }) 
    }) 
}) 
+1

này đã làm các trick! Chỉ có một chỉnh sửa tôi sẽ thực hiện cho câu trả lời của bạn: bạn cần phải khôi phục lại người nghe ban đầu trước khi thực hiện xác nhận, vì khẳng định sẽ đưa ra một lỗi. – Domenic

+0

Điều này thực sự nên có trong tài liệu của Mocha! Tôi đã mất một giờ để tìm câu trả lời này .. Việc ghi lại các lỗi sai (và không kiểm tra) của Mocha kết hợp với thực tế là không có thông báo lỗi nào được hiển thị nếu bạn không ném một đối tượng Lỗi chuẩn (theo lời khuyên của Crockford), thật khó để tìm ra lý do tại sao bài kiểm tra không thành công. –

+7

Dường như trong phiên bản mới nhất của nút (v0.10.5 tại thời điểm nhận xét này) 'process.listeners (eventName)' trả về một bản sao của mảng nghe, và vì vậy gọi 'pop()' trên nó sẽ không thực sự loại bỏ người nghe khỏi bộ phát. Bạn sẽ cần phải thêm dòng sau đây sau khi pop: 'process.removeListener ('uncaughtException', originalException);' –

0

Nếu mã async của bạn là thực hiện trong vòng một miền - và đó thường là trường hợp - bạn cần phải thay đổi người nghe lỗi trên tên miền thay vì quá trình này.

Cho rằng bạn có thể sử dụng:

it('should produce an unhandled exception', function (done) { 

    // Remove Mocha's error listener 
    var originalErrorListeners = process.domain.listeners('error'); 
    process.domain.removeAllListeners('error'); 

    // Add your own error listener to check for unhandled exceptions 
    process.domain.on('error', function() { 

     // Add the original error listeners again 
     process.domain.removeAllListeners('error'); 
     for (var i = 0; i < originalErrorListeners.length; i+=1) { 
      process.domain.on('error', originalErrorListeners[i]); 
     } 

     // For the sake of simplicity we are done after catching the unhandled exception 
     done(); 

    }); 

    // This would be your async application code you expect to throw an exception 
    setTimeout(function() { 
     throw new Error(); 
    }); 

}); 
-1

Căn cứ vào timoxley & Casey Foster, trong nút v6 ++

const assert = require('assert') 

describe('throwNextTick', function() { 
    it('works as expected', function(next) { 

     function cb(err) { 
      assert.equal(err instanceof Error, true) 
      next() 
     } 

     function test(){ 
      process.nextTick(() => { 
       throw new Error('err') 
      }) 
     } 

     process.prependOnceListener('uncaughtException', cb) 
     test() 

    }) 
}) 
+0

Cú pháp này ('import') không hoạt động trong Node.js. – Domenic

+0

bạn luôn có thể chạy mocha bằng '' '--require babel-core/register''' để có' '' import/export''' và thêm .babelrc với '' '{" presets ": [" es2015 "]}' '' – syarul

Các vấn đề liên quan