Trong thử nghiệm mocha trong khi gọi hàm không đồng bộ, làm thế nào để tránh lỗi hết thời gian chờ: vượt quá thời gian chờ 2000ms


200

Trong ứng dụng nút của tôi, tôi đang sử dụng mocha để kiểm tra mã của mình. Trong khi gọi nhiều hàm không đồng bộ bằng mocha, tôi gặp lỗi hết thời gian ( Error: timeout of 2000ms exceeded.). Làm thế nào tôi có thể giải quyết điều này?

var module = require('../lib/myModule');
var should = require('chai').should();

describe('Testing Module', function() {

    it('Save Data', function(done) {

        this.timeout(15000);

        var data = {
            a: 'aa',
            b: 'bb'
        };

        module.save(data, function(err, res) {
            should.not.exist(err);
            done();
        });

    });


    it('Get Data By Id', function(done) {

        var id = "28ca9";

        module.get(id, function(err, res) {

            console.log(res);
            should.not.exist(err);
            done();
        });

    });

});

nó có phải là một bài kiểm tra tích hợp? Sẽ mất rất nhiều thời gian để chạy thử - có lẽ bạn nên xem xét sơ khai - github.com/thlorenz/proxyquire có thể giúp bạn.
surui

@surui cảm ơn bạn tôi sẽ xem xét điều đó
sachin

Tôi có thể khuyên bạn nên sử dụng lời hứa cho những thứ không đồng bộ và thử nghiệm nó sau đó rất dễ dàng với Chai như lời hứa
Krym

Câu trả lời:


344

Bạn có thể đặt thời gian chờ khi chạy thử nghiệm:

mocha --timeout 15000

Hoặc bạn có thể đặt thời gian chờ cho từng bộ hoặc từng thử nghiệm theo chương trình:

describe('...', function(){
  this.timeout(15000);

  it('...', function(done){
    this.timeout(15000);
    setTimeout(done, 15000);
  });
});

Để biết thêm thông tin xem các tài liệu .


3
phiên bản ngắn hơn là -t. nếu bạn sử dụng mocha-test để chạy mocha từ tác vụ grunt, thì điều này cũng được hỗ trợ trong đối tượng tùy chọn options:{timeout:15000}.
Svassr

5
FYI: không truyền chức năng mũi tên cho Mocha. mochajs.org/#arrow-fifts
c0ming

4
Các chức năng mũi tên không được khuyến khích trong liên kết ở trên. Nó chỉ nói rằng bạn chỉ cần biết những gì họ làm để bạn không gặp rắc rối khi cần truy cập vào bối cảnh. Tôi không bao giờ cần bối cảnh, vì việc dựa vào thời gian chờ là rất mong manh và tất cả các thử nghiệm của tôi đều chạy trong vài ms, nhưng tôi gặp phải vấn đề tương tự khi sử dụng thử nghiệm sinon. Vẫn sử dụng lambdas 99% thời gian.
oligofren

26
TypeError: this.timeout is not a functionkhi sử dụng"mocha": "^3.5.0"
Junior Mayhé

5
@adi bạn có chắc là bạn không sử dụng chức năng mũi tên? Về async / đang chờ nó trong tài liệu nên hoạt động (và cũng giống như sử dụng lời hứa). Âm thanh như một câu hỏi khác mặc dù.
Andreas Hultgren

80

Tôi thấy rằng "giải pháp" của việc chỉ tăng thời gian chờ làm lu mờ những gì đang thực sự xảy ra ở đây, đó là

  1. Mã và / hoặc các cuộc gọi mạng của bạn quá chậm (nên là 100 ms để có trải nghiệm người dùng tốt)
  2. Các xác nhận (kiểm tra) đều thất bại và có gì đó đang nuốt các lỗi trước khi Mocha có thể hành động theo chúng.

Bạn thường gặp # 2 khi Mocha không nhận được lỗi xác nhận từ cuộc gọi lại. Điều này được gây ra bởi một số mã khác nuốt ngoại lệ lên ngăn xếp. Cách xử lý đúng đắn này là sửa mã và không nuốt lỗi .

Khi mã bên ngoài nuốt lỗi của bạn

Trong trường hợp đó là chức năng thư viện mà bạn không thể sửa đổi, bạn cần nắm bắt lỗi xác nhận và tự mình chuyển nó sang Mocha. Bạn làm điều này bằng cách gói cuộc gọi lại xác nhận của bạn trong một khối thử / bắt và chuyển bất kỳ ngoại lệ nào cho trình xử lý đã thực hiện.

it('should not fail', function (done) { // Pass reference here!

  i_swallow_errors(function (err, result) {
    try { // boilerplate to be able to get the assert failures
      assert.ok(true);
      assert.equal(result, 'bar');
      done();
    } catch (error) {
      done(error);
    }
  });
});

Bản tóm tắt này tất nhiên có thể được trích xuất thành một số chức năng tiện ích để làm cho bài kiểm tra dễ chịu hơn một chút:

it('should not fail', function (done) { // Pass reference here!
    i_swallow_errors(handleError(done, function (err, result) {
        assert.equal(result, 'bar');
    }));
});

// reusable boilerplate to be able to get the assert failures
function handleError(done, fn) {
    try { 
        fn();
        done();
    } catch (error) {
        done(error);
    }
}

Tăng tốc kiểm tra mạng

Ngoài ra, tôi khuyên bạn nên nhận lời khuyên về việc bắt đầu sử dụng các cuống thử nghiệm cho các cuộc gọi mạng để thực hiện các thử nghiệm mà không phải phụ thuộc vào mạng hoạt động. Sử dụng Mocha, Chai và Sinon, các bài kiểm tra có thể trông giống như thế này

describe('api tests normally involving network calls', function() {

    beforeEach: function () {
        this.xhr = sinon.useFakeXMLHttpRequest();
        var requests = this.requests = [];

        this.xhr.onCreate = function (xhr) {
            requests.push(xhr);
        };
    },

    afterEach: function () {
        this.xhr.restore();
    }


    it("should fetch comments from server", function () {
        var callback = sinon.spy();
        myLib.getCommentsFor("/some/article", callback);
        assertEquals(1, this.requests.length);

        this.requests[0].respond(200, { "Content-Type": "application/json" },
                                 '[{ "id": 12, "comment": "Hey there" }]');
        expect(callback.calledWith([{ id: 12, comment: "Hey there" }])).to.be.true;
    });

});

Xem tài liệu của Sinonnise để biết thêm.


Tôi có một bộ thử nghiệm khổng lồ và tôi đã thực hiện tất cả các lời hứa trong thông số kỹ thuật của mình để đảm bảo rằng tất cả chúng đều được gọi done()vào cuối lời hứa và tôi đã chế giễu các cuộc gọi mạng bằng cách sử dụng Angular $httpBackend, nhưng không gặp may. Kết thúc mọi thông số kỹ thuật với một lần thử không có vẻ rất thực dụng. Bất cứ một đề nghị nào khác? cảm ơn!
Gustavo Matias

@GustavoMatias Bạn thực sự chưa đề cập đến vấn đề của bạn là gì, chỉ nói rằng đây không phải là giải pháp cho bất cứ điều gì bạn đang gặp vấn đề. Xin hãy giải thích :-) Các bài kiểm tra của bạn không đủ nhanh? Có phải họ thất bại đôi khi, nhưng bạn muốn biết tại sao? Khó đoán những gì bạn dự định đạt được.
oligofren

chào @oligofren! đó thực sự không phải là lời giải thích tốt nhất Có một lời giải thích chi tiết hơn về vấn đề của tôi ở đây stackoverflow.com/questions/34510048/ cảm ơn!
Gustavo Matias

"Nói chung, cách sạch nhất (nhưng xấu nhất) để xử lý vấn đề này là bọc mã của bạn bằng một lần thử / bắt và chuyển bất kỳ trường hợp ngoại lệ nào cho trình xử lý đã thực hiện." Không, đây không phải là cách sạch nhất. Không phải bằng một cú sút xa. Cách sạch nhất là viết mã không nuốt ngoại lệ. Mỗi lần tôi thấy ai đó phàn nàn rằng Mocha không phát hiện ra một bài kiểm tra thất bại, đó là vì có gì đó nuốt phải ngoại lệ. Thêm một try.... catch...công việc xung quanh lỗi trong mã được kiểm tra thay vì sửa nó.
Louis

@Louis bạn có thể có thể đúng về những người ở đây, nhưng tôi không thể xác minh nó ra khỏi màu xanh. Dù sao, mọi người có vấn đề với Mocha dường như không thể bắt được một số lỗi và đây là một cách xử lý. cách tiếp cận đã cho của bạn giả định rằng mã nuốt lỗi không phải là một số chức năng thư viện hoặc tương tự, trong trường hợp đó, nó sẽ không được giải quyết dễ dàng như vậy.
oligofren

7

Hơi muộn một chút nhưng ai đó có thể sử dụng điều này trong tương lai ... Bạn có thể tăng thời gian chờ kiểm tra của mình bằng cách cập nhật tập lệnh trong gói.json bằng cách sau:

"scripts": { "test": "test --timeout 10000" //Adjust to a value you need }

Chạy thử nghiệm của bạn bằng cách sử dụng lệnh test


Đã làm cho tôi! Cảm ơn bạn!
RayLovless

5

Nếu bạn đang sử dụng các chức năng mũi tên:

it('should do something', async () => {
  // do your testing
}).timeout(15000)

1

Đối với tôi, vấn đề thực sự là chức năng mô tả, khi được cung cấp chức năng mũi tên, khiến mocha bị mất thời gian chờ và hành xử không nhất quán. (Sử dụng ES6)

vì không có lời hứa nào bị từ chối nên tôi đã nhận được lỗi này mọi lúc cho các thử nghiệm khác nhau đã thất bại trong khối mô tả

Vì vậy, nó trông như thế nào khi không hoạt động đúng:

describe('test', () => { 
 assert(...)
})

và điều này hoạt động bằng cách sử dụng chức năng ẩn danh

describe('test', function() { 
 assert(...)
})

Hy vọng nó sẽ giúp được ai đó, cấu hình của tôi cho phần trên: (nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)


0

Vấn đề của tôi đã không gửi phản hồi lại, vì vậy nó đã bị treo. Nếu bạn đang sử dụng express, hãy đảm bảo rằng res.send (dữ liệu), res.json (dữ liệu) hoặc bất kỳ phương thức api nào bạn muốn sử dụng đều được thực thi cho tuyến đường bạn đang thử nghiệm.


0

Đảm bảo giải quyết / từ chối các lời hứa được sử dụng trong các trường hợp thử nghiệm, có thể là gián điệp hoặc sơ khai để đảm bảo họ giải quyết / từ chối.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.