I am writing test cases for angular2 components.
I had created a service which uses observable stream as below:
import {Injectable} from '@angular/core'
import {Subject} from 'rxjs/Subject';
import {User} from './user.model';
@Injectable()
export class UserService {
selectedUserInstance:User = new User();
// Observable selectedUser source
private selectedUserSource = new Subject<User>();
// Observable selectColumn stream
selectedUser$ = this.selectedUserSource.asObservable();
// service command
selectUser(user:User) {
this.selectedUserInstance=user;
this.selectedUserSource.next(user);
}
}
Now In my component I have subscribed to this stream as :
getSelectedUser() {
this.subscriptionUser = this.userService.selectedUser$.subscribe(
selectedUser => {
this.selectedUser = selectedUser;
}
);
}
Now in my spec.ts file, I want to mock this stream as :
spyOn(userService, 'selectedUser$')
.and.returnValue(Observable.of({
'name': 'bhushan',
'desc': 'student'
}));
But it keeps giving me following error:
Error: spyOn could not find an object to spy upon for selectColumn$()
is there any way to do this?
I am stuck on this issue for very long time now.
any inputs?
thanks
Test the Component logic using SpyOn - Testing Angular. SpyOn is a Jasmine feature that allows dynamically intercepting the calls to a function and change its result. This example shows how spyOn works, even if we are still mocking up our service.
fixture. detectChanges() tells Angular to run change-detection. Finally! Every time it is called, it updates data bindings like ng-if, and re-renders the component based on the updated data. Calling this function will cause ngOnInit to run only the first time it is called.
Introduction. Mocking is a great idea for testing Angular apps because it makes maintenance easier and helps reduce future bugs. There are a few complex tools, such as XUnit, for mocking an Angular CLI project. You can execute the mocking methods described in this guide only if you use vanilla Jasmine + Angular Testbed ...
selectedUser$
isn't a method, so you can't spy on it. Instead, if you want you can just assign it a your observable
rapidColumnService.selectedUser$ = Observable.of({
'name': 'bhushan',
'desc': 'student'
})
NOTE (UPDATE): see updated usage of
of
here: Property 'of' does not exist on type 'typeof Observable
But honestly, if that is your complete service, I don't see why you even need to mock it. It is simple enough where using the real service probably wouldn't hurt. If you use the real service, then you can just selectUser
whenever you want to emit something new to the component under test.
Another thing you could also do is instead of using an Observable
is to use a Subject
. A Subject
is also an Observable
, but it lets you emit values, making it easier to mock values to test.
rapidColumnService.selectedUser$ = new BehaviorSubject<any>();
Then when you want to send a value
rapidColumnService.selectedUser$.next({
'name': 'bhushan',
'desc': 'student'
});
Depending on how you have your component set up and the subscription, you may just want to use a plain Subject
instead of a `BehaviorSubject. See this post for more info.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With