Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 如何测试订阅引发的错误_Angular_Unit Testing_Angular Test - Fatal编程技术网

Angular 如何测试订阅引发的错误

Angular 如何测试订阅引发的错误,angular,unit-testing,angular-test,Angular,Unit Testing,Angular Test,我正在测试angular 4中下面的调用函数 import { Component, OnInit } from '@angular/core'; import { AppService } from './app.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class Ap

我正在测试angular 4中下面的调用函数

import { Component, OnInit } from '@angular/core';
import { AppService } from './app.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  title = 'jasmine-error-test';

  constructor(private appService: AppService) { }

  ngOnInit(): void {
    this.call();
  }

  call() {
    return this.appService.load().subscribe((res) => {
      this.title = res;
    }, (err) => {
      throw new Error('Failed');
    });
  }

}
为了测试订阅中抛出错误的部分,我将执行以下操作

describe('when call is called', () => {
    describe('when the service returns an error', () => {
      let app;
      beforeEach(async(() => {
        const fixture = TestBed.createComponent(AppComponent);
        app = fixture.componentInstance;
        (service.load as jasmine.Spy).and.returnValue(Observable.throw({
          status: 406,
          error: {
            message: 'Test 406 error'
          }
        }));
      }));
      it('it should throw a  matching error', async(() => {
        expect(() => { app.call(); }).toThrowError('Failed');
      }));
    });
  });
但是测试失败了,并且出现了错误

Expected function to throw an Error.

如果我使用debugger窗口,它会显示抛出错误的行被命中,但仍然无法通过测试。谁能告诉我发生了什么事。

有意思的问题。对可观测数据的错误处理是很棘手的。正如您所发现的,重新抛出错误是非常重要的,因为捕获此类错误的方法在try/catch块中,但这不适用于异步代码。:)关于这一点,网上有很多很好的讨论,我发现了一个:

我建议重构你的代码。如果发生错误,您可以像使用
this.title
一样捕获组件变量中的详细信息。可能将其称为this.error
,然后您可以测试它是否为null(无错误),或者是否有值(如果有错误)。也许像这样重构:

call() {
    return this.appService.load().subscribe((res) => {
        this.title = res;
    }, (err) => {
        this.error = err;
        // throw new Error('Failed');
    });
}
it('it should capture any error in this.error', () => {
    // expect(() => { app.call(); }).toThrowError('Failed');
    app.call();
    expect(app.error).toEqual(/* testError */);
});
那么您的测试将如下所示:

call() {
    return this.appService.load().subscribe((res) => {
        this.title = res;
    }, (err) => {
        this.error = err;
        // throw new Error('Failed');
    });
}
it('it should capture any error in this.error', () => {
    // expect(() => { app.call(); }).toThrowError('Failed');
    app.call();
    expect(app.error).toEqual(/* testError */);
});

如果这对您有帮助,下面是一个stackblitz,我想尝试一下关于这个问题的一些想法:

您的函数确实不会抛出任何错误。它订阅一个可观察的,并且在函数返回很久之后,当错误http响应最终返回时,订阅时传递的错误回调抛出错误。抛出这个错误有什么意义?你希望发生什么事情,而仅仅让原始错误传播就不会发生?你所说的传播是什么意思?在哪里传播?这是我的组件,没有上游。在整个项目中,存在一个angular应用程序级错误处理程序组件,用于捕获任何未处理的错误并优雅地处理。这就是我抛出错误的原因。这是我的组件,没有上游。因此我的问题是:抛出错误,而不是让原始未处理的错误传播到应用程序级错误处理程序,这有什么意义?句柄不会得到原始的、详细的http错误,而只会得到一个毫无意义的、神秘的错误,告诉您“失败”。这有什么意义?谢谢你的建议,我已经尝试过了,而且成功了,但是我正在编写测试,代码最初是由其他人编写的,我不允许更改代码。但是谢谢你的回复。此外,我认为在代码中有一个通用的angular errorhandler,它应该捕获这些错误并优雅地处理它们。