hoa nhài: Cuộc gọi lại không đồng bộ không được gọi trong thời gian chờ được chỉ định bởi jasmine.DEFAULT_TIMEOUT_INTERVAL


140

Tôi có một dịch vụ góc gọi là requestNotificationChannel:

app.factory("requestNotificationChannel", function($rootScope) {

    var _DELETE_MESSAGE_ = "_DELETE_MESSAGE_";

    function deleteMessage(id, index) {
        $rootScope.$broadcast(_DELETE_MESSAGE_, { id: id, index: index });
    };

    return {
       deleteMessage: deleteMessage
    };

});

Tôi đang cố gắng thử nghiệm dịch vụ này bằng hoa nhài:

"use strict";

describe("Request Notification Channel", function() {
    var requestNotificationChannel, rootScope, scope;

    beforeEach(function(_requestNotificationChannel_) {
        module("messageAppModule");

        inject(function($injector, _requestNotificationChannel_) {
            rootScope = $injector.get("$rootScope");
            scope = rootScope.$new();
            requestNotificationChannel = _requestNotificationChannel_;
        })

        spyOn(rootScope, '$broadcast');
    });


    it("should broadcast delete message notification", function(done) {

        requestNotificationChannel.deleteMessage(1, 4);
        expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4 });
        done();       
    });
});

Tôi đã đọc về Hỗ trợ không đồng bộ trong Jasmine, nhưng vì tôi chưa quen với thử nghiệm đơn vị với javascript nên không thể làm cho nó hoạt động.

Tôi đang nhận được một lỗi:

Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL

và thử nghiệm của tôi mất quá nhiều thời gian để thực hiện (khoảng 5s).

Ai đó có thể giúp tôi cung cấp ví dụ làm việc về mã của tôi với một số giải thích?


1
Xử lý các sự kiện thường được thực hiện trong một chu trình tiêu hóa. Hãy thử thêm phạm vi. $ Áp dụng () vào thử nghiệm của bạn thay vì sử dụng mẫu thử nghiệm không đồng bộ của Jasmine
Eitan Peer

Điều này không làm việc. Tôi đã thêm phạm vi. $ Áp dụng (); ngay sau khi gọi requestNotificationChannel.deleteMessage (1, 4) nhưng tôi đã nhận được cùng một lỗi ...
Mdb

Tôi gặp lỗi tương tự khi các kiểm tra async mất nhiều thời gian hơn so với Jestmong đợi - rất phổ biến trong khi gỡ lỗi và mất một thời gian để kiểm tra các biến.
Dan Dascalescu

Thay vào đó, hãy thử sử dụng thời gian chờ ít hơn. Tôi đã gặp lỗi này khi sử dụng timeout = 5000. Tôi đã thay thế nó bằng 2000 và nó đã hoạt động với tôi!
Marina Rịaz

1
Để lại đây để giúp ai đó trong đôi giày của tôi. Tôi đã có lỗi này trong khi chạy thử nghiệm bên trong một container docker. Các xét nghiệm đôi khi sẽ vượt qua mà không có bất kỳ vấn đề, nhưng đôi khi thất bại. Tôi đoán đó là một loại điều kiện chủng tộc nhưng không thể hiểu tại sao. Tôi nhận ra rằng tôi có một afterEachbước đang xóa cơ sở dữ liệu (sử dụng deleteManyphương thức). Việc thêm jest.setTimeout(30000);vào beforeAllphương thức dường như đã khắc phục điều này đối với tôi - Tôi đoán vì việc xóa cơ sở dữ liệu là một cuộc gọi mạng (trong điều kiện), đôi khi mất hơn 3 giây và ném.
nkhil

Câu trả lời:


231

Có một đối số trong itchức năng của bạn ( donetrong mã bên dưới) sẽ khiến Jasmine thực hiện cuộc gọi không đồng bộ.

//this block signature will trigger async behavior.
it("should work", function(done){
  //...
});

//this block signature will run synchronously
it("should work", function(){
  //...
});

Nó không tạo ra sự khác biệt về những gì doneđối số được đặt tên, sự tồn tại của nó là tất cả những gì quan trọng. Tôi gặp vấn đề này từ quá nhiều bản sao / mì ống.

Các tài liệu hỗ trợ không đồng bộ của Jasmine lưu ý rằng đối số (được đặt tên doneở trên) là một cuộc gọi lại có thể được gọi để cho Jasmine biết khi nào một chức năng không đồng bộ hoàn tất. Nếu bạn không bao giờ gọi nó, Jasmine sẽ không bao giờ biết bài kiểm tra của bạn đã hoàn thành và cuối cùng sẽ hết thời gian.


3
Điều tương tự cũng đúng với args trong mô tả (trong góc, bạn cần gọi chích trong mô tả để làm điều đó)
Narretz

@MartinBliss Nó là tài liệu, tôi vừa đề nghị một chỉnh sửa để tham khảo tài liệu: stackoverflow.com/suggested-edits/2434606
Vincent

39
Lưu ý đối với các nhân viên Google ngẫu nhiên gặp phải câu hỏi này trong tương lai: nếu bạn đang sử dụng Protractor và gặp phải vấn đề này, câu trả lời này không phải là điều bạn đang tìm kiếm - Protractor tự gọi lại cuộc gọi lại.
Vincent

Nó đã khắc phục vấn đề của tôi và nó được gây ra bởi cùng một "bản sao / mì ống"
shaikh

1
@Vincent những gì người dùng Protractor phát hành sau đó nếu lỗi này xảy ra?
Bruno Bieri

57

Ngay cả đối với các kiểm tra không đồng bộ, vẫn có thời gian chờ tắt trong trường hợp này, Bạn có thể khắc phục lỗi này bằng cách tăng giá trị cho thời gian chờ giới hạn để đánh giá cuộc gọi lại không đồng bộ Jasmine

describe('Helper', function () {
    var originalTimeout;

    beforeEach(function() {
        originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
        jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000000;
    });

    afterEach(function() {
      jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
    });

    it('Template advance', function(doneFn) {
        $.ajax({
            url: 'public/your-end-point.mock.json',
            dataType: 'json',
            success: function (data, response) {
                // Here your expected using data
                expect(1).toBe(1)
                doneFn();
            },
            error: function (data, response) {
                // Here your expected using data
                expect(1).toBe(1)
                doneFn();
            }
        });
    });
});

Nguồn: http://jasmine.github.io/2.0/intributiontion.html#section-42


1
Điều này có vẻ như không "đúng cách" để làm điều đó, nhưng sau khi thêm một vài số không cho phép thử Selenium của tôi để chạy, đây là một hack cần thiết.
emery

Hoa nhài ban đầu.DEFAULT_TIMEOUT_INTERVAL là 60000 ms. Vì vậy, ví dụ này sẽ thực sự làm cho nó ngắn hơn sáu lần.
Waltari

Bạn nói đúng Tôi chỉ cần đặt một số ngẫu nhiên trong ví dụ này, cảm ơn :)
gsacheadotoledo 17/10/18

20

Lỗi này cũng có thể được gây ra bằng cách bỏ đi tiêm khi khởi tạo dịch vụ / nhà máy hoặc bất cứ điều gì. Ví dụ, nó có thể được ném bằng cách làm điều này:

var service;
beforeEach(function(_TestService_) {
    service = _TestService_;
});

Để khắc phục, chỉ cần bọc chức năng bằng hàm tiêm để truy xuất dịch vụ đúng cách:

var service;
beforeEach(inject(function(_TestService_) {
    service = _TestService_;
}));

13
import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing';

sử dụng fakeAsync

beforeEach(fakeAsync (() => {

//your code

}));



describe('Intilalize', () => {
        it('should have a defined component', fakeAsync(() => {
            createComponent();
            expect(_AddComponent.ngOnInit).toBeDefined();
        }));
    });

6

Bạn có thể sử dụng plugin karma-jasmine để đặt khoảng thời gian chờ mặc định trên toàn cầu.

Thêm cấu hình này trong karma.conf.js

module.exports = function(config) {
  config.set({
    client: {
      jasmine: {
        timeoutInterval: 10000
      }
    }
  })
}

5

Lỗi này bắt đầu từ màu xanh đối với tôi, trong một bài kiểm tra luôn hoạt động. Tôi không thể tìm thấy bất kỳ đề xuất nào có ích cho đến khi tôi nhận thấy Macbook của mình hoạt động chậm chạp. Tôi nhận thấy CPU bị chặn bởi một quá trình khác, mà tôi đã giết. Lỗi Jasmine async biến mất và các bài kiểm tra của tôi lại ổn.

Đừng hỏi tôi tại sao, tôi không biết. Nhưng trong hoàn cảnh của tôi, nó dường như là thiếu tài nguyên hệ thống có lỗi.


5
Có thể, khi CPU của bạn rảnh, tác vụ đã hoàn thành trước khi hết thời gian mặc định. Khi CPU bận, tác vụ bạn đang kiểm tra mất quá nhiều thời gian để hoàn thành.
Shane

5

Đây là một quan sát nhiều hơn là một câu trả lời, nhưng nó có thể giúp những người khác cũng thất vọng như tôi.

Tôi liên tục nhận được lỗi này từ hai bài kiểm tra trong bộ của tôi. Tôi nghĩ rằng tôi chỉ đơn giản là đã phá vỡ các thử nghiệm với phép tái cấu trúc mà tôi đang thực hiện, vì vậy sau khi sao lưu các thay đổi không hoạt động, tôi đã quay lại mã trước đó, hai lần (hai lần sửa đổi lại) nghĩ rằng nó sẽ thoát khỏi lỗi. Làm như vậy chẳng thay đổi gì. Tôi đã đuổi theo đuôi cả ngày hôm qua, và một phần của sáng nay mà không giải quyết được vấn đề.

Tôi đã nản lòng và kiểm tra mã trên máy tính xách tay sáng nay. Chạy toàn bộ bộ kiểm tra (khoảng 180 bài kiểm tra), không có lỗi. Vì vậy, các lỗi không bao giờ có trong mã hoặc các bài kiểm tra. Đã quay lại hộp dev của tôi và khởi động lại nó để xóa bất cứ thứ gì trong bộ nhớ có thể gây ra sự cố. Không thay đổi, cùng một lỗi trong hai bài kiểm tra. Vì vậy, tôi đã xóa thư mục từ máy của mình và kiểm tra lại. Voila! Không có lỗi.

Không biết điều gì gây ra nó, hoặc làm thế nào để sửa nó, nhưng xóa thư mục làm việc và kiểm tra lại nó đã sửa bất kể nó là gì.

Hy vọng điều này sẽ giúp được ai đó.


1
Cảm ơn người đàn ông, tôi đã phát điên về điều này. Tôi đã khởi động lại PC của mình và thế là xong
yngrdyn

Trong trường hợp của tôi, tôi chỉ chạy lại lệnh và nó đã giải quyết vấn đề này. Tôi đã tải lại nóng cho các bài kiểm tra đơn vị và mỗi lần nó đều thất bại. Tôi đã phải dừng lại và chạy lệnh một lần nữa.
Jignesh

4

Đừng sử dụng done, chỉ để trống chức năng gọi.


Vui lòng sửa lại cho tôi nếu tôi sai nhưng vì tôi đã hiểu nó chỉ làm cho bộ kiểm tra kết thúc trước khi kiểm tra và thông báo lỗi bị thay thế. Điều đó có nghĩa là bất kỳ khẳng định nào sẽ không phá vỡ bài kiểm tra vì bộ kiểm tra đã kết thúc trước khi xác nhận được chạy. Điều này cũng có nghĩa là (tôi đã thấy hành vi tương tự) rằng một thử nghiệm khác cho thấy lỗi mà thử nghiệm này tạo ra. Cuối cùng, điều đó có nghĩa là mọi thứ có vẻ ổn để bắt đầu nhưng khi số lượng thử nghiệm tăng lên, vấn đề sẽ xuất hiện không liên tục.
LosManos

3

Bạn cũng nhận được lỗi này khi mong đợi một cái gì đó trong beforeAllchức năng!

describe('...', function () {

    beforeAll(function () {
        ...

        expect(element(by.css('[id="title"]')).isDisplayed()).toBe(true);
    });

    it('should successfully ...', function () {

    }
}

2

Trong trường hợp của tôi, lỗi này là do sử dụng "fixture.detectChanges ()" không đúng cách. Có vẻ như phương thức này là một trình lắng nghe sự kiện (async) sẽ chỉ phản hồi lại một cuộc gọi lại khi phát hiện ra các thay đổi. Nếu không có thay đổi nào được phát hiện, nó sẽ không gọi lại, dẫn đến lỗi hết thời gian. Hi vọng điêu nay co ich :)


2

Hoạt động sau khi loại bỏ scopetham chiếu và các đối số chức năng:

"use strict";

describe("Request Notification Channel", function() {
    var requestNotificationChannel, rootScope;

    beforeEach(function() {
        module("messageAppModule");

        inject(function($injector, _requestNotificationChannel_) {
            rootScope = $injector.get("$rootScope");
            requestNotificationChannel = _requestNotificationChannel_;
        })
        spyOn(rootScope, "$broadcast");
    });


    it("should broadcast delete message notification with provided params", function() {
        requestNotificationChannel.deleteMessage(1, 4);
        expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4} );
    });
});

0

Theo ghi nhận của @mastablasta, nhưng cũng nói thêm rằng nếu bạn gọi đối số 'done' hay đúng hơn là tên nó hoàn thành bạn chỉ cần gọi callback hoàn thành () trong thử nghiệm của bạn khi nó được thực hiện.

// this block signature will trigger async behavior.
it("should work", function(done){
  // do stuff and then call done...
  done();
});

// this block signature will run synchronously
it("should work", function(){
  //...
});

0

hoa nhài.DEFAULT_TIMEOUT_INTERVAL = 100000;

Giữ điều này trong khối giải quyết vấn đề của tôi.

it('', () => {
 jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
});

0

Những gì tôi đã làm là: Đã thêm / Cập nhật mã sau đây:

framework: 'jasmine',
jasmineNodeOpts: 
{
    // Jasmine default timeout
    defaultTimeoutInterval: 60000,
    expectationResultHandler(passed, assertion) 
    {
      // do something
    },
}

3
Vui lòng giải thích lý do tại sao mã này hoạt động, thay vì chỉ đăng nó mà không có lời giải thích.
Kobe

Vì vậy, về cơ bản khi bạn thực hiện một thử nghiệm và mất nhiều thời gian hơn dự kiến, nó sẽ thất bại vì thời gian chờ mặc định đã được đáp ứng và tập lệnh không tiến lên trong thực thi. Điều này có thể xảy ra do một số điều kiện không được đáp ứng (Ví dụ: khả năng hiển thị, tải trang). Bây giờ nếu hết thời gian mặc định của bạn giống như 1000ms >> tập lệnh sẽ thất bại thường xuyên vì chỉ một giây và có thể có nhiều yếu tố thêm vào sự thất bại của tập lệnh của bạn. Tuy nhiên, việc tăng khoảng thời gian chờ của bạn có thể khiến trình duyệt / trình điều khiển chờ lâu hơn để đáp ứng các điều kiện.
Zeeshan

2
Được rồi, bây giờ từ đó vào bài viết của bạn; bạn nên cố gắng tránh trả lời bằng mã mà không cần giải thích :)
Kobe

0

Thay vì

beforeEach(() => {..

sử dụng

beforeEach(fakeAsync(() => {..

0

Có vẻ như bài kiểm tra đang chờ một số cuộc gọi lại không bao giờ đến. Có thể là do thử nghiệm không được thực hiện với hành vi không đồng bộ.

Trước tiên, hãy xem nếu chỉ sử dụng fakeAsync trong kịch bản "nó" của bạn:

it('should do something', fakeAsync(() => {

Bạn cũng có thể sử dụng flush()để đợi hàng đợi microTask kết thúc hoặc tick()chờ một khoảng thời gian được chỉ định.


-2

Nếu bạn có một đối số ( done) trong ithàm, hãy cố gắng loại bỏ nó cũng như nó gọi trong chính hàm đó:

it("should broadcast delete message notification", function(/*done -> YOU SHOULD REMOVE IT */) {

    requestNotificationChannel.deleteMessage(1, 4);
    expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4 });
    // done(); -> YOU SHOULD REMOVE IT        
});

4
Không có bất kỳ lời giải thích tại sao câu trả lời này không hữu ích.
Gary

2
câu trả lời này đã giải quyết vấn đề của tôi ... kiểm tra góc là một cơn ác mộng!
Benjamin Caure
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.