Unit test 'success' and 'error' observable response in component for Angular 2
Solution 1
I would create two mocks - one that throws an error:
class ObserverThrowServiceStub {
getData() {
return Observable.throw(new Error('Test error'));
}
}
and one that returns successfully.
class ObserverSuccessServiceStub {
getData() {
return Observable.from(data);
}
}
Then, instead of providing the same mock service to all tests, you provide the failing/successful mock service appropriately depending on the test in question (obviously you'll need to move your module configuration into a configurable method that you call from within each test rather than in the .beforeEach()
code.
There is a really nice article on testing Angular services using Observables here (which uses exactly this model): http://www.zackarychapple.guru/angular2/2016/11/25/angular2-testing-services.html
Solution 2
someObj.ObservableReturninFunction().subscribe(
(obj)=> {
conosle.log(obj.message);
},
(err)=>{
console.log(err.message);
}
});
when success;
SpyOn(someObj,"ObservableReturninFunction").and.returnValue(
Observable.of({message: "something"}));
when erro:
SpyOn(someObj,"ObservableReturninFunction").and.returnValue(
Observable.throw({message: "some-error"}));
Solution 3
You can use Jasmine Spy to spyOn
your mock service class's method which returns an Observable.
More detail is here: Jasmine - how to spyOn instance methods
bmd
Updated on June 30, 2021Comments
-
bmd about 3 years
I'm writing a unit test for a component that makes a call to a service OnInit. If the response is a 'success' one action taken and another for an 'error'.
What is the best way to test both cases? I've created a simplified version of the component and unit test. Something that I could easily test against in both cases.
I've attempted to implement the solution here but I must be off on the implementation. I've also attempted to throw an error as you will see in the spec and comments.
Component
@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..."; } }
Spec
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..."); }); });