Angular 2组件中的单元测试“成功”和“错误”可观察响应

时间:2017-07-13 15:05:57

标签: angular jasmine

我正在为一个调用服务OnInit的组件编写单元测试。如果响应是“成功”,则采取一项措施,另一项采取“错误”。

测试这两种情况的最佳方法是什么?我已经创建了组件和单元测试的简化版本。在这两种情况下我都可以轻易测试的东西。

我试图实施解决方案here,但我必须关闭实施。我也试图抛出一个错误,你会在规范和评论中看到。

组件

@Component({
  selector: 'app-observer-throw-unit-test',
  template: '<p>{{ data }}</p>'
})
export class ObserverThrowUnitTestComponent implements OnInit {
    public data: string;

    constructor(private _observerThrowService: ObserverThrowService) { }

    ngOnInit() {
        this._observerThrowService.getData().subscribe(
            (data) => {
                this.data = data;
            },
            (error) => {
                this.redirect()
            }
        )
    }

    redirect() {
        this.data = "Redirecting...";
    }

}

规格

const data: string = "Lorem ipsum dolor sit amet.";

const ObserverThrowServiceStub = {
  error: false,
  getData() {
    return Observable.create((observer) => {
      if(this.error) {
        observer.error(new Error());
      } else {
        observer.next(data);
      }
      observer.complete();
    })
  }
}

describe('ObserverThrowUnitTestComponent', () => {
  let component: ObserverThrowUnitTestComponent;
  let fixture: ComponentFixture<ObserverThrowUnitTestComponent>;
  let _observerThrowService: ObserverThrowService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ObserverThrowUnitTestComponent ],
      providers: [
        { provide: ObserverThrowService, useValue: ObserverThrowServiceStub },
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ObserverThrowUnitTestComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
    _observerThrowService = TestBed.get(ObserverThrowService);
  });

  it('should set "data" to "Lorem ipsum dolor sit amet." on success', () => {
      expect(component.data).toEqual("Lorem ipsum dolor sit amet.");
  });

  it('should set "data" on "Redirecting..." on error',() => {
    ObserverThrowServiceStub.error = true;
    // spyOn(_observerThrowService, "getData").and.returnValue(Observable.throw("error")); // This did not work and returned : TypeError: undefined is not a constructor (evaluating 'Observable_1.Observable.throw("error")') in src/test.ts
    spyOn(_observerThrowService, "getData")
    expect(component.data).toEqual("Redirecting...");
  });

  it('should set "data" on "Redirecting..." on error',() => {
    // This works after setting error to true in the previous test
    spyOn(_observerThrowService, "getData")
    expect(component.data).toEqual("Redirecting...");
  });

});

4 个答案:

答案 0 :(得分:8)

我会创建两个模拟 - 一个抛出错误:

class ObserverThrowServiceStub {
  getData() {
    return Observable.throw(new Error('Test error'));
  }
}

并且成功返回。

class ObserverSuccessServiceStub {
  getData() {
    return Observable.from(data);
  }
}

然后,不是为所有测试提供相同的模拟服务,而是根据相关测试适当地提供失败/成功的模拟服务(显然,您需要将模块配置移动到您从中调用的可配置方法在每个测试中,而不是在.beforeEach()代码中。

这里有一篇关于使用Observables测试Angular服务的非常好的文章(它正好使用了这个模型): http://www.zackarychapple.guru/angular2/2016/11/25/angular2-testing-services.html

答案 1 :(得分:0)

install karma-firefox-launcher with
npm install karma-firefox-launcher --save-dev then



karma.config.js file  (the only part you will edit is this and leave other content)


plugins: [
      require('karma-jasmine'),
      require('karma-firefox-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
browsers: ['Firefox']    


input only firefox karma.config.js, chrome has issues currently

答案 2 :(得分:0)

我会在存根中添加一个公共错误标志。然后,我可以在beforeEach()中创建一个存根,并只需在每个测试用例中更新错误标志,即可确定要使用哪个版本的getData。

class ObserverServiceStub {
  public error = false;
  getData() {
    if (this.error) {
      return Observable.throw(new Error('Test error'));
    } else {
      return Observable.from(data);
    }
  }
}

答案 3 :(得分:0)

您可以使用Jasmine Spy spyOn来模拟服务类的方法,该方法返回一个Observable。 此处有更多详细信息:Jasmine - how to spyOn instance methods