【问题标题】:How do I debug a "[object ErrorEvent] thrown" error in my Karma/Jasmine tests?如何在我的 Karma/Jasmine 测试中调试“[object ErrorEvent] throwed”错误?
【发布时间】:2018-01-25 02:38:33
【问题描述】:

我有几个失败的测试只输出[object ErrorEvent] thrown。我在控制台中看不到任何可以帮助我查明违规代码的内容。我需要做些什么来追踪这些吗?

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

【问题讨论】:

  • 你能包含更多的错误吗?喜欢前后多行错误?
  • [object ErrorEvent] thrown 就是它所说的一切。之前或之后都没有。
  • 幸运的是,我刚刚在您发布此问题的同时遇到了这个问题,结果证明它是一个“流氓”脚本标签(也可能是 css 链接),需要要删除(我的问题与 CORS 有关),或者在 css 的情况下,我只是添加了 crossorigin="anonymous"。检查您的代码中是否有此类脚本/css 标签,在我的情况下,我发现问题是由完全不同的组件引起的!
  • 你在使用 angular cli 不是吗? @DarrellBrogdon
  • @TheDude 你是如何缩小这个脚本的范围的?逐行?或者是否有一些调试过程可以帮助您缩小范围?我有同样的问题,我必须继续的唯一信息是消息:在 afterAll 中引发了错误。如果我通过将it() 更改为fit() 来隔离测试本身,即使只有单个测试正在运行,错误仍然会被抛出。有针对此类错误的调试建议吗?

标签: angular angular-cli karma-jasmine


【解决方案1】:

仅供参考:您可以在测试运行后打开 DevTools Console 找到确切的错误。

作为快速修复,您可以尝试运行您的tests without sourcemaps

CLI v6.0.8 及更高版本
--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,所以现在问题已经解决了。

【讨论】:

  • 这对我有用。它有助于揭示问题出在未定义的输入绑定上。
  • 对于 angular-cli 6,--sourceMap=false 似乎可以工作。
  • 典型的前端解决方案
  • 此解决方案不再有效。它曾经是,但在 6.2.4 中它不会
  • 我在随机组件中抛出 Uncaught [object Object],在某些运行中我什么也得不到...:S 我讨厌 Angular 测试。
【解决方案2】:

如果 sourcemap=false 没有帮助,请尝试 1)打开浏览器运行测试 2)点击调试按钮 3) 打开控制台

错误会在那里

【讨论】:

  • 我什至不需要点击调试按钮。只是打开开发者控制台对我有用。
  • 太棒了!我到处都添加了 sourcemap 选项,但最后这给了我需要的信息
  • --sourcemaps=false 对我不起作用,但这完美无瑕!谢谢!
  • 如果浏览器在测试后立即关闭,这并没有真正的帮助。我想我会写一堆无用的测试来保持窗口打开,就像某种穴居人一样。
【解决方案3】:

尝试通过从终端运行测试来获得更具描述性的错误消息,如下所示:

ng test -sm=false

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

it('should...')

fit('should...') 

现在只有 fit 之前的测试才会运行。 要在运行测试后让浏览器保持打开状态,请像这样运行测试:

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

就个人而言,我遇到过两次这个错误。两者都只在调用 fixture.detectChanges() 时触发。

第一次时,我通过在我的 .html 文件中更安全地使用字符串插值解决了这个问题。

不安全示例:

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

Safe(r) 示例(注意问号):

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

这同样适用于属性绑定:

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

第二次,我在 .html 文件中使用了 DatePipe,但我使用它的模拟属性不是日期。

.html 文件:

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

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

let startDate = 'blablah';

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

let startDate = '2018-01-26';

【讨论】:

【解决方案4】:

这是因为 jasmine 框架无法处理 ErrorEvent 类型,因此它不会提取错误消息,而是在该对象上调用 error.toString()

我刚刚在 jasmine repo 提交了一个问题 https://github.com/jasmine/jasmine/issues/1594

只要不修复,你可以在 node_modules 文件夹中临时修补你安装的 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';
}

这有助于识别问题。

【讨论】:

  • 这在 jasmine-core@2.99.1 中对我有用。但是,我不得不在node_modules/jasmine_core/lib/jasmine_core/jasmine.js 中修补它
  • 太好了 - 花了一分钟才找到这篇文章,但它救了我的命。谢谢。相同的 jasmine-core 版本
  • 更改后,它只为我打印了uncaught,这没有帮助。所以我添加了代码来打印error 对象及其属性。 if(error){ // message+=error; for(var propName in error) { propValue = error[propName] message+='error prop: '+propName+', value: '+propValue; } } 。这提供了帮助我调试的额外信息 - egerror prop: filename, value: blob:http://localhost:9881/11777e3a-28d8-414e-9047-cee7d328e843
【解决方案5】:

对我来说,这与在组件的 ngOnInit 中解决承诺有关。我必须使用asyncfakeAsync 和勾选以及使用spyOn 删除异步服务

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

Angular - How to unit test component with asynchronous service call

【讨论】:

    【解决方案6】:

    TL;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 就会消失。

    我的 userService 有一个这样的用户:

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

    所以0 只是在索引0 处获取此用户。

    否则,在正常运行我的应用程序时,当用户从我的用户表中选择要编辑的用户时,会评估 this.route.snapshot.paramMap.get('id')

    所以在我的 HTML 中,*ngFor="let user of users; index as i" 循环显示所有用户,然后是 routerLink="/edit/{{i}}",这样您就可以点击每个用户的编辑按钮,点击后转到例如http://localhost:4200/edit/0 编辑上述管理员用户的详细信息。

    【讨论】:

      【解决方案7】:

      如何在每个测试用例之后进行清理:

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

      【讨论】:

      • 我在某处读到,TestBed 在每次测试时都会重置。
      • 我的情况是它有助于清理下一次测试。
      【解决方案8】:

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

      我的解决方法只是在下面添加要处理(错误)的代码块:

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

      【讨论】:

      • 这也是我的情况,我正在多播,其中一位订阅者没有处理错误。
      【解决方案9】:

      我遇到了同样的问题。发生此错误的一种方式是当您尝试访问模板中的任何 null 或 undefined 时。确保对这些变量进行安全检查。

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

      template.html

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

      改为这样做

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

      【讨论】:

        【解决方案10】:

        如果您为 Karma 测试运行程序打开了 Chrome 窗口,则可以帮助您打开开发人员工具并检查那里的控制台。对我来说,这帮助我发现应用程序无法在未定义的数组上使用 Array.findIndex 方法(因为数据结构是按日期字符串组织的,例如 data[2018][3][28] 和我碰巧指向了错误的日期),但测试并没有停止在错误处,而是继续运行。

        【讨论】:

        • 非常感谢!我本来希望信息会出现在控制台中,你救了我几个小时的生命:)
        【解决方案11】:

        对我来说,问题是我在测试中不小心使用了 auth0-lock 库。

        【讨论】:

          【解决方案12】:

          这似乎是一个异步问题,因为在我的一个组件规范中添加了足够多的its 之后,我能够得到一个可用的错误消息,它指向该文件中的一个文件和行(它是相关的到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();
              });
            });
          

          【讨论】:

            【解决方案13】:

            您的比赛或异步测试可能设置不正确或使用不正确。我会假设需要修复调试案例并忽略命令行通过。只要不断刷新 karma 测试运行器(浏览器),以防错误 [object ErrorEvent] thrown 间歇性出现,然后确保您已正确实现异步条件。

            希望这行得通。

            【讨论】:

              【解决方案14】:

              [object ErrorEvent] 抛出

              此错误表明您有未定义的内容。根据我的经验,最简单的调试方法是:

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

              【讨论】:

              • 这实际上是最有用的提醒:在我的测试中,我有一个模拟身份验证服务,它错过了一个方法。看似无关,组件中的一项测试失败了,但在隔离时却没有。多亏了console.log,我才将晦涩的[object ErrorEvent] thrown追踪到那个远程丢失的方法:)
              【解决方案15】:

              在我的情况下,问题出在服务上,因为其中一个对象在测试运行期间将未定义。

              服务代码示例类似于下面对 dom 的访问,

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

              引用此服务的规范失败并出现错误“[object ErrorEvent] throw”。

              我在所有涉及此的规范中模拟了我的服务对象,问题得到了解决。

              模拟服务

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

              【讨论】:

                【解决方案16】:

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

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

                由于 Karma 不知道此代理,它不断在控制台中抛出错误,即找不到 API 端点。 所以在查看了 Karma 文档后,我发现我可以做的是在 karma.conf.js 中添加“代理”属性,并使用来自 proxy.conf.json 的相同对象:

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

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

                【讨论】:

                  【解决方案17】:

                  最后,什么对我有用:

                      TestBed.resetTestingModule();
                    })
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-05-01
                    • 2019-02-17
                    • 1970-01-01
                    相关资源
                    最近更新 更多