jasmine:在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时时间内未调用异步回调

IT技术 javascript angularjs unit-testing asynchronous jasmine
2021-01-31 23:43:58

我有一个名为 的角度服务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
    };

});

我正在尝试使用 jasmine 对该服务进行单元测试:

"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();       
    });
});

我阅读了 Jasmine 中的异步支持,但由于我对使用 javascript 进行单元测试比较陌生,因此无法使其工作。

我收到一个错误:

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

我的测试执行时间太长(大约 5 秒)。

有人可以帮助我提供我的代码的工作示例并提供一些解释吗?

6个回答

在您的it函数中(done在下面的代码中)有一个参数将导致 Jasmine 尝试异步调用。

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

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

它不会有所作为什么done说法而得名,它的存在才是最重要的。我从太多的副本/面食中遇到了这个问题。

Jasmine异步支持文档指出参数(done如上所示)是一个回调,可以调用它让 Jasmine 知道异步函数何时完成。如果你从不调用它,Jasmine 永远不会知道你的测试已经完成并且最终会超时。

@Vincent 如果发生此错误,Protractor 用户会遇到什么问题?
2021-03-22 23:43:58
它解决了我的问题,它是由相同的cuplrit“copy/pasta”引起的
2021-03-25 23:43:58
描述中的 args 也是如此(在 angular 中,你需要在描述中调用注入来做到这一点)
2021-03-31 23:43:58
@MartinBliss 已记录在案,我刚刚建议进行编辑以参考文档:stackoverflow.com/suggested-edits/2434606
2021-04-05 23:43:58
请注意将来遇到此问题的随机 Google 员工:如果您正在使用 Protractor 并遇到此问题,则此答案不是您要寻找的 - Protractor 会自行调用回调。
2021-04-06 23:43:58

即使对于异步测试,在这种情况下也会出现超时,您可以通过增加限制超时的值来评估异步 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();
            }
        });
    });
});

来源:http : //jasmine.github.io/2.0/introduction.html#section-42

原来的 jasmine.DEFAULT_TIMEOUT_INTERVAL 是 60000 毫秒。所以这个例子实际上会使它缩短六倍。
2021-03-16 23:43:58
你说得对,我只是在这个例子中放了一个随机数,谢谢:)
2021-03-29 23:43:58
这似乎不是“正确的方法”,但在为我的 Selenium 测试添加几个额外的零之后,这是一个需要的 hack。
2021-04-08 23:43:58

此错误也可能是由于在初始化服务/工厂或其他任何事情时省略了注入而引起的。例如,它可以通过这样做抛出:

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

要修复它,只需使用注入包装函数以正确检索服务:

var service;
beforeEach(inject(function(_TestService_) {
    service = _TestService_;
}));
import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing';

使用假异步

beforeEach(fakeAsync (() => {

//your code

}));



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

您可以使用karma-jasmine插件全局设置默认超时间隔。

在 karma.conf.js 中添加此配置

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