我有一个名为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秒)。
有人可以通过一些解释帮我提供我的代码的工作示例吗?
答案 0 :(得分:200)
在it
函数中使用参数(下面的代码中为done
)将导致Jasimne尝试异步调用。
//this block signature will trigger async behavior.
it("should work", function(done){
//...
});
//this block signature will run synchronously
it("should work", function(){
//...
});
done
参数的命名并没有什么区别,它的存在才是最重要的。我从太多的副本/面食中遇到了这个问题。
Jasmin Asynchronous Support文档注意到参数(上面名为done
)是一个回调,可以调用它让Jasmine知道异步函数何时完成。如果您从未打过电话,Jasmine将永远不会知道您的测试已经完成并最终会超时。
答案 1 :(得分:18)
在初始化服务/工厂或其他任何情况时,也可以通过省略注入来引起此错误。例如,可以通过这样做抛出它:
var service;
beforeEach(function(_TestService_) {
service = _TestService_;
});
要修复它,只需使用inject包装函数以正确检索服务:
var service;
beforeEach(inject(function(_TestService_) {
service = _TestService_;
}));
答案 2 :(得分:8)
import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing';
使用 fakeAsync
beforeEach(fakeAsync (() => {
//your code
}));
describe('Intilalize', () => {
it('should have a defined component', fakeAsync(() => {
createComponent();
expect(_AddComponent.ngOnInit).toBeDefined();
}));
});
答案 3 :(得分:5)
这个错误对我来说是开始的,在一直有效的测试中。在我注意到我的Macbook运行缓慢之前,我无法找到任何有用的建议。我注意到CPU被另一个进程挂起,我杀了它。 Jasmine异步错误消失了,我的测试再次正常。
不要问我为什么,我不知道。但在我的情况下,似乎缺乏系统资源。
答案 4 :(得分:3)
这更多的是观察,而不是答案,但它可能会对像我一样沮丧的其他人有所帮助。
我一直从套件中的两个测试中得到此错误。我以为我只是用我的重构破坏了测试,所以在撤消更改不起作用之后,我又恢复到了早期的代码,两次(返回两次修订)都认为它可以消除错误。这样做并没有改变。昨天整天和今天早上的一部分时间,我都追不着尾巴。
今天早上,我感到沮丧,并把代码签到了笔记本电脑上。运行了整个测试套件(约180个测试),没有错误。因此,错误永远不会出现在代码或测试中。回到我的开发箱并重新启动它,以清除内存中可能引起问题的所有内容。没有变化,在相同的两个测试中出现相同的错误。因此,我从计算机中删除了该目录,然后将其检出。瞧!没有错误。
不知道是什么原因引起的,或如何修复它,但是删除了工作目录并检出它已经修复了。
希望这对某人有帮助。
答案 5 :(得分:3)
不要使用done
,只需将函数调用留空即可。
答案 6 :(得分:2)
在beforeAll
函数中期待某些内容时,您也会遇到此错误!
describe('...', function () {
beforeAll(function () {
...
expect(element(by.css('[id="title"]')).isDisplayed()).toBe(true);
});
it('should successfully ...', function () {
}
}
答案 7 :(得分:2)
在我的情况下,这个错误是由于“fixture.detectChanges()”的使用不当引起的。似乎这个方法是一个事件监听器(async),它只会在检测到更改时响应回调。如果未检测到任何更改,则不会调用回调,从而导致超时错误。希望这会有所帮助:)
答案 8 :(得分:2)
您可以使用karma-jasmine插件来全局设置默认超时间隔。
在karma.conf.js中添加此配置
module.exports = function(config) {
config.set({
client: {
jasmine: {
timeoutInterval: 10000
}
}
})
}
答案 9 :(得分:1)
删除scope
引用和函数参数后工作:
"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} );
});
});
答案 10 :(得分:1)
代替
beforeEach(() => {..
使用
beforeEach(fakeAsync(() => {..
答案 11 :(得分:0)
正如@mastablasta所指出的,还要补充一点,如果您调用'done'参数,或者更确切地说将其命名为 completed ,则只需在测试完成后调用回调complete()即可。 / p>
// 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(){
//...
});
答案 12 :(得分:0)
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
将其保留在区块中可以解决我的问题。
it('', () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
});
答案 13 :(得分:0)
我所做的是:添加/更新了以下代码:
framework: 'jasmine',
jasmineNodeOpts:
{
// Jasmine default timeout
defaultTimeoutInterval: 60000,
expectationResultHandler(passed, assertion)
{
// do something
},
}
答案 14 :(得分:0)
如果done
函数中有参数(it
),请尝试将其删除,并在函数本身内调用:
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
});
答案 15 :(得分:0)
测试似乎正在等待永远不会出现的回调。可能是因为测试没有以异步行为执行。
首先,查看是否仅在“ it”场景中使用了fakeAsync:
it('should do something', fakeAsync(() => {
您还可以使用flush()
等待microTask队列完成,或者使用tick()
等待指定的时间。
答案 16 :(得分:0)
在我的例子中,超时的原因是使用 providedIn: 'root'
注入服务失败。目前尚不清楚为什么注入失败,也不清楚如果显然没有可用的提供程序实例,为什么没有早期错误。
我可以通过手动提供一个值来解决这个问题:
TestBed.configureTestingModule({
declarations: [
// ...
],
imports: [
// ...
],
providers: [
// ...
{ provide: MyService, useValue: { /* ... */ } },
]
}).compileComponents();