如何在 Karma/Jasmine 测试中调试“[ object ErrorEvent ]抛出”错误?

我有几个失败的测试,只输出 [object ErrorEvent] thrown。我在控制台中没有看到任何有助于我精确定位违规代码的东西。我需要做什么来追踪这些吗?

[编辑] : 我正在运行 Karma v1.70,Jasmine v2.7.0

75215 次浏览

仅供参考: 一旦您的测试运行,您可以找到由 open DevTools 控制台抛出的确切错误。

作为一个快速修复程序,你可以尝试运行你的 没有源图的测试:

CLI v6.0.8 and above
--source-map=false

CLI v6.0.x 早期版本
--sourceMap=false

CLI v1.x
--sourcemaps=false

ng test -sm=false快捷方式也可能有用

关于 https://github.com/angular/angular-cli/issues/7296还有一个未解决的问题

更新 : 我也有这个问题,所以我只是迁移到最新的 cli,并确保所有的软件包更新在 package.json也我完全重新安装的 node_modules所以现在的问题已经消失了。

DR: 它可能与测试路由有关。

我也收到 [object ErrorEvent] thrown了。 一小时后,追踪到一行代码。

this.username = this.userService.getUser(this.route.snapshot.paramMap.get('id'))[0];

问题在于试图评估 this.route.snapshot.paramMap.get('id')的测试环境。

如果我用 0代替它,[object ErrorEvent] thrown就消失了。

我的用户服务有一个这样的用户:

public users = [ ["admin", "First name", "Surname", etc... ] ].

所以 0只能得到这个用户,位于 0索引处。

否则,当正常运行我的应用程序时,当用户从我的用户表中选择一个用户进行编辑时,将计算 this.route.snapshot.paramMap.get('id')

So in my HTML, *ngFor="let user of users; index as i" loops to display all the users then routerLink="/edit/\{\{i}}" so you can click on edit buttons for each user, which when clicked go to e.g. http://localhost:4200/edit/0 to edit the aforementioned admin user's details.

For me it was related to having a promise resolved in the ngOnInit of a component. I had to use async, fakeAsync and tick as well as stubbing out the async service with spyOn

beforeEach(async(
//... initialise testbed and component
))
beforeEach(fakeAsync(
// ... setup mocks then call:
component.ngOnInit()
tick()
fixture.detectChanges()
))

角度-如何使用异步服务调用对组件进行单元测试

您可能有一个设置不完全正确或使用不正确的竞争或异步测试。我假设需要修复调试用例,并忽略命令行的传递。只要持续刷新 Karma 测试运行程序(浏览器) ,以防错误 [object ErrorEvent] thrown断断续续地出现,然后确保您正确地实现了异步条件。

希望能成功。

如果通过从终端运行测试得到更具描述性的错误消息,请尝试这样做:

ng test -sm=false

在您的测试中,您可以替换

it('should...')

fit('should...')

现在只运行 合身之前的测试。 若要在运行测试后保持浏览器处于打开状态,请像下面这样运行测试:

ng test -sm=false --single-run false

就我个人而言,我已经遇到过两次这样的错误。

first时,我在 html 文件中更安全地使用字符串插值解决了这个问题。

不安全 例子:

<p>\{\{user.firstName}}</p>

安全(r) 示例(注意问号) :

<p>\{\{user?.firstName}}</p>

这同样适用于财产约束:

<p [innerText]="user?.firstName"></p>

第二时代,我在我的。Html 文件,但是我使用它的模拟属性不是日期。

Html 文件:

<p>\{\{startDate | date: 'dd-MM-yyyy'}}</p>

. ts (模拟数据)文件(错了) :

let startDate = 'blablah';

. ts (模拟数据)文件(正确) :

let startDate = '2018-01-26';

对于我来说,问题是我有一个测试,其中我不小心使用了 Auth0-lock库。

我也有同样的问题。发生此错误的一种方式是尝试访问模板中的任何 null 或未定义内容。确保对这些变量进行安全检查。

例如,当组件加载时配置未定义时,这将抛出[ object: ErrorEvent ]。

翻译: 奇芳

<div *ngIf="config.options">
.....
......
</div>

不如这样

<div *ngIf="config?.options">
.....
......
</div>

这似乎是一个异步问题,因为在我的一个组件规格中添加了足够多的 it之后,我能够得到一个可用的错误消息,它指向一个文件和该文件中的一行(它与 paramMap相关)。

在测试 ParamMap 的规范中,我只是添加了:

  describe('this test', () => {
it('will succeed', () => {
expect(true).toBeTruthy();
});


it('will succeed', () => {
expect(true).toBeTruthy();
});


it('will succeed', () => {
expect(true).toBeTruthy();
});


it('will succeed', () => {
expect(true).toBeTruthy();
});
});

如果 source map = false 不起作用,请尝试 1)开启浏览器进行测试 2) click debug button 3)打开控制台

错误就在那里

enter image description here

在每个测试用例之后进行清理怎么样:

  afterEach(() => {
TestBed.resetTestingModule();
})

这是因为 Jasmine 框架不能处理 ErrorEvent 类型,所以它不提取错误消息,而是对该对象调用 error.toString()

我刚向 Jasmine 回收公司提交了申请 https://github.com/jasmine/jasmine/issues/1594

只要它没有被修复,您就可以在 node _ module 文件夹中临时修补已安装的 jasmine 包。对我来说是的

node_modules/jasmine/node_modules/lib/jasmine-core/jasmine.js

然后将 ExceptionFormatter 的实现从

if (error.name && error.message) {
message += error.name + ': ' + error.message;
} else {
message += error.toString() + ' thrown';
}

这个

if (error.name && error.message) {
message += error.name + ': ' + error.message;
} else if (error.message) {
message += error.message;
} else {
message += error.toString() + ' thrown';
}

它有助于识别问题。

[ object ErrorEvent ]抛出

这个错误表明你有一些未定义的东西。根据我的经验,调试它最简单的方法是:

it('should create', () => {
console.log(component);
// You can check in the browser log which property is undefined
});

在我的例子中,问题出在服务上,因为其中一个对象在测试运行期间没有定义。

Service code sample was something like below access to dom,

  const elem = this.document.querySelector(element) as HTMLElement;
elem.scrollIntoView({param1: ''});

引用此服务的规格说明出现错误“ [ object ErrorEvent ]抛出”。

我在所有引用这个的 spec 中模拟了我的服务对象,问题得到了解决。

模拟服务

class MockService {
serviceMethod(div) : void {
testElement = document.querySelector('div') as HTMLElement;
return testElement;
}
}

并在提供程序中使用此模拟服务对象,如下所示,

beforeEach(async(() => {


TestBed.configureTestingModule({
declarations: [Component],
providers: [
{ provide: Service, useClass: MockService },
],
})
.compileComponents();
}));

帮助是,如果你已经为你的 Karma 测试运行者打开了 Chrome 窗口,打开开发工具并检查那里的控制台。对我来说,这帮助我发现应用程序不能在未定义的数组上使用 Array.findIndex 方法(因为数据结构是由日期字符串组织的,比如 data [2018][3][28] ,而我恰好指向了错误的日期) ,但是测试并没有因为错误而停止,而是继续运行。

我在 proxy.conf.json 中定义的应用程序中使用了一个代理,比如:

'/api': { 'target': 'some path', 'changeOrigin': false }

因为 Karma 没有意识到这个代理,所以它在控制台中不断抛出无法找到 API 端点的错误。 因此,在查看了 Karma 文档之后,我发现我可以做的是在 Karma.con.js 中添加具有来自 proxy.con.json 的相同对象的“代理”属性:

proxies: { '/api': { 'target': 'some path', 'changeOrigin': false }}

控制台中的错误消失了,不再抛出[ object errorEvent ]。

最后,对我有效的方法是:

    TestBed.resetTestingModule();
})

对我来说,这是由于没有为我订阅的 api 定义错误处理程序造成的。

我的解决方案只是在下面添加了要处理的代码块(err) :

it('reports an error to subscribers of api calls if not authenticated', (done) => {
let obsDataFound = dataService.find(1);
obsDataFound.subscribe((app) => {
// not expecting this block to be called
done();
}, (err) => {
// This is the err block that I added that solved the problem
expect(true).toBeTruthy();
done();
});


let testRequest = httpMock.expectOne({method: 'GET'});
const mockErrorResponse = { status: 401, statusText: 'Unauthorized test status message' };
testRequest.flush(appTest, mockErrorResponse);
});