2010-11-10 31 views
354

Tôi đang cố gắng viết một bài kiểm tra cho số Jasmine Test Framework mà dự kiến ​​sẽ xảy ra lỗi. Hiện tại tôi đang sử dụng Jasmine Node.js integration from GitHub.Làm thế nào để viết một bài kiểm tra dự kiến ​​một lỗi sẽ được ném vào Jasmine?

Trong mô-đun Node của tôi, tôi có đoạn mã sau:

throw new Error("Parsing is not possible"); 

Bây giờ tôi cố gắng viết một bài kiểm tra mà hy vọng lỗi này:

describe('my suite...', function() { 
    [..] 
    it('should not parse foo', function() { 
    [..] 
     expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible")); 
    }); 
}); 

Tôi cũng đã cố gắng Error() và một số biến thể khác và chỉ không thể tìm ra cách làm cho nó hoạt động.

+3

Để vượt qua đối số chức năng đang được thử nghiệm, mà không sử dụng một chức năng ẩn danh, hãy thử 'Function.bind': http://stackoverflow.com/ a/13233194/294855 –

Trả lời

628

bạn nên đi qua một chức năng vào expect(...) gọi. Mã này bạn có ở đây:

// incorrect: 
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible")); 

đang cố gắng để thực sự gọiparser.parse(raw) trong một nỗ lực để vượt qua kết quả vào expect(...),

Hãy thử sử dụng một chức năng vô danh thay vì:

expect(function(){ parser.parse(raw); }).toThrow(new Error("Parsing is not possible")); 
+21

Nếu bạn không cần phải vượt qua đối số quá, bạn cũng có thể chỉ cần vượt qua hàm để mong đợi: 'expect (parser.parse) .toThrow (...)' – SubmittedDenied

+47

Mẹo hữu ích: Bạn có thể chỉ cần gọi là 'mong đợi (blah) .toThrow() '. Không có đối số có nghĩa là kiểm tra để thấy rằng nó ném ở tất cả. Không yêu cầu kết hợp chuỗi. Xem thêm: http://stackoverflow.com/a/9525172/1804678 – Jess

+1

Theo tôi, rõ ràng hơn là mục đích của bài kiểm tra khi gói trong một hàm ẩn danh. Ngoài ra, nó vẫn nhất quán trong tất cả các thử nghiệm khi, ví dụ, bạn phải truyền tham số cho hàm đích để làm cho nó ném. – Beez

55

Bạn đang sử dụng:

expect(fn).toThrow(e) 

Nhưng nếu bạn sẽ có một cái nhìn vào chức năng bình luận (dự kiến ​​là string):

294 /** 
295 * Matcher that checks that the expected exception was thrown by the actual. 
296 * 
297 * @param {String} expected 
298 */ 
299 jasmine.Matchers.prototype.toThrow = function(expected) { 

Tôi cho rằng có lẽ bạn nên viết nó như thế này (using lambda - anonymous function):

expect(function() { parser.parse(raw); }).toThrow("Parsing is not possible"); 

Điều này được xác nhận trong ví dụ sau:

expect(function() {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible"); 

Douglas Crockford mạnh mẽ khuyến cáo phương pháp này, thay vì sử dụng "ném Lỗi mới()" (mẫu chiều):

throw { 
    name: "Error", 
    message: "Parsing is not possible" 
} 
+3

Trên thực tế, xem xét mã toThrow sẽ vui vẻ lấy một đối tượng ngoại lệ/hoặc/một chuỗi. Kiểm tra các cuộc gọi nó đang thực hiện để expected.message ví dụ. –

+1

Nó đường nối để cho phép chuỗi như là một tác dụng phụ của chuỗi không có bất động sản tin nhắn – mpapis

+1

Cảm ơn rất nhiều mà làm việc. Tôi vẫn chấp nhận câu trả lời của Pete, beacuse câu trả lời của mình làm cho nó rõ ràng hơn với tôi, rằng tôi _have_ để sử dụng một lambda. Vẫn +1 :-) Cảm ơn! – echox

22

tôi thay thế matcher của Jasmine's toThrow bằng phần sau, cho phép bạn so khớp thuộc tính tên của exception hoặc thuộc tính message của nó. Đối với tôi điều này làm cho các bài kiểm tra dễ dàng hơn để viết và ít giòn, như tôi có thể làm như sau:

throw { 
    name: "NoActionProvided", 
    message: "Please specify an 'action' property when configuring the action map." 
} 

và sau đó kiểm tra như sau:

expect (function() { 
    .. do something 
}).toThrow ("NoActionProvided"); 

này cho phép tôi tinh chỉnh thông điệp ngoại lệ sau mà không vi phạm kiểm tra, khi điều quan trọng là nó ném loại ngoại lệ dự kiến.

Đây là sự thay thế cho toThrow cho phép này:

jasmine.Matchers.prototype.toThrow = function(expected) { 
    var result = false; 
    var exception; 
    if (typeof this.actual != 'function') { 
    throw new Error('Actual is not a function'); 
    } 
    try { 
    this.actual(); 
    } catch (e) { 
    exception = e; 
    } 
    if (exception) { 
     result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected) || this.env.equals_(exception.name, expected)); 
    } 

    var not = this.isNot ? "not " : ""; 

    this.message = function() { 
    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { 
     return ["Expected function " + not + "to throw", expected ? expected.name || expected.message || expected : " an exception", ", but it threw", exception.name || exception.message || exception].join(' '); 
    } else { 
     return "Expected function to throw an exception."; 
    } 
    }; 

    return result; 
}; 
+3

Một cách tiếp cận tốt đẹp nhưng là {name: '...', message: '...'} là một đối tượng Error thích hợp trong JavaScript? – Marc

+1

Nhận xét hay @Marc. Bạn nói đúng, thuộc tính tên không phải là tiêu chuẩn. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error, nhưng điều đó có sai không? – Jess

+3

@Jake! Tôi tìm thấy một cách tốt hơn !!!! Bạn có thể gọi đơn giản là 'expect (blah) .toThrow() '. Không có đối số có nghĩa là kiểm tra để thấy rằng nó ném ở tất cả. Không yêu cầu kết hợp chuỗi. Xem thêm: http://stackoverflow.com/a/9525172/1804678 – Jess

5

Đối với những người yêu thích coffeescript

expect(=> someMethodCall(arg1, arg2)).toThrow() 
7

Tôi biết rằng là mã hơn nhưng bạn cũng có thể làm:

try 
    do something 
    @fail Error("should send a Exception") 
catch e 
    expect(e.name).toBe "BLA_ERROR" 
    expect(e.message).toBe 'Message' 
+0

Tôi có xu hướng thích khía cạnh 'tự tài liệu' này ... làm cho nó rất rõ ràng rằng bạn đang thử nghiệm đơn vị trạng thái lỗi – JRulle

19

Một giải pháp thanh lịch hơn là tạo ra một chức năng ẩn danh với mục đích duy nhất là bọc một thứ khác, là sử dụng sốcủa eschức năng. Hàm liên kết tạo ra một hàm mới, khi được gọi, có từ khóa this được đặt thành giá trị được cung cấp, với một chuỗi các đối số đã cho trước bất kỳ khi nào hàm mới được gọi.

Thay vì:

expect(function() { parser.parse(raw, config); }).toThrow("Parsing is not possible");

xem xét:

expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");

Cú pháp ràng buộc cho phép bạn kiểm tra các chức năng với this giá trị khác nhau, và theo ý kiến ​​của tôi khiến cho xét nghiệm dễ đọc hơn. Xem thêm: https://stackoverflow.com/a/13233194/1248889

6

Như đã đề cập trước đó, một chức năng cần phải được thông qua để toThrow vì nó là chức năng bạn đang mô tả trong bài kiểm tra của bạn: "Tôi hy vọng chức năng này để ném x"

expect(() => parser.parse(raw)) 
    .toThrow(new Error('Parsing is not possible')); 

Nếu sử dụng Jasmine-Matchers bạn cũng có thể sử dụng một trong những điều sau đây khi chúng phù hợp với tình huống;

// I just want to know that an error was 
// thrown and nothing more about it 
expect(() => parser.parse(raw)) 
    .toThrowAnyError(); 

hoặc

// I just want to know that an error of 
// a given type was thrown and nothing more 
expect(() => parser.parse(raw)) 
    .toThrowErrorOfType(TypeError); 
+2

Đó là 'mong đợi (foo) .toThrowError (TypeError);' trong Jasmine 2.5: https://jasmine.github.io/2.5/introduction –

0

Đối với những ai vẫn có thể phải đối mặt với vấn đề này, đối với tôi là giải pháp đăng tải không làm việc và nó vẫn tiếp tục ném lỗi này: Error: Expected function to throw an exception. Sau này tôi nhận ra rằng chức năng mà tôi đã mong đợi để ném một lỗi là một chức năng async và hy vọng sẽ được từ chối và sau đó ném lỗi và đó là những gì tôi đã làm trong mã của tôi:

throw new Error('REQUEST ID NOT FOUND'); 

và đó là những gì tôi đã làm trong thử nghiệm của tôi và nó làm việc:

it('Test should throw error if request not found', willResolve(() => { 
     const promise = service.getRequestStatus('some-id'); 
       return expectToReject(promise).then((err) => { 
        expect(err.message).toEqual('REQUEST NOT FOUND'); 
       }); 
      })); 
Các vấn đề liên quan