Reputation: 71
I have this spec:
import {TestBed, ComponentFixture} from '@angular/core/testing';
import { LoginComponent } from './login.component';
import {UserService} from "../services/user.service";
import {HttpModule} from "@angular/http";
import {FormsModule} from "@angular/forms";
import {RouterTestingModule} from "@angular/router/testing";
describe('LoginComponent', () => {
let component: LoginComponent;
let service: UserService;
let fixture: ComponentFixture<LoginComponent>;
class UserServiceStub {
userLogin(email: string, password: string) {
return [email, password];
}
}
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [LoginComponent],
imports: [HttpModule, FormsModule, RouterTestingModule],
providers: [
{provide: UserService, useClass: UserServiceStub}
]
});
service = TestBed.get(UserService);
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should call the service when the sign in button is clicked', () => {
component.onLoginButtonClick();
expect(service.userLogin("pippo", "pluto")).toBe(["pippo", "pluto"]);
});
});
I can't figure out what is the displayed issue:
TypeError: this.userService.userLogin(...).catch is not a function at LoginComponent.onLoginButtonClick (http://0.0.0.0:9882/base/src/test.ts:71519:68) at Object.<anonymous> (http://0.0.0.0:9882/base/src/test.ts:71485:19) at ZoneDelegate.invoke (http://0.0.0.0:9882/base/src/test.ts:108270:26) at ProxyZoneSpec.onInvoke (http://0.0.0.0:9882/base/src/test.ts:103404:39) at ZoneDelegate.invoke (http://0.0.0.0:9882/base/src/test.ts:108269:32) at Zone.run (http://0.0.0.0:9882/base/src/test.ts:108066:43) at Object.<anonymous> (http://0.0.0.0:9882/base/src/test.ts:103119:34) at attemptSync (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1950:24) at ZoneQueueRunner.QueueRunner.run (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1938:9) at ZoneQueueRunner.QueueRunner.execute (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1923:10) at ZoneQueueRunner.jasmine.QueueRunner.ZoneQueueRunner.execute (http://0.0.0.0:9882/base/src/test.ts:103149:42) at Spec.queueRunnerFactory (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:714:35) at Spec.execute (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:371:10) at Object.fn (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2579:37) at attemptAsync (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1980:24)
It looks like the test goes on the real service and not on the UserServiceStub.
Upvotes: 4
Views: 1481
Reputation: 1269
The issue you are observing is that your userLogin
method from your real service is returning a Promise while the userLogin
method from your stub class is returning an array. Since an array does not have a catch
method, it is causing an error. What you are trying to accomplish is this:
import {TestBed, ComponentFixture} from '@angular/core/testing';
import { LoginComponent } from './login.component';
import {UserService} from "../services/user.service";
import {HttpModule} from "@angular/http";
import {FormsModule} from "@angular/forms";
import {RouterTestingModule} from "@angular/router/testing";
describe('LoginComponent', () => {
let component: LoginComponent;
let service: UserService;
let fixture: ComponentFixture<LoginComponent>;
let userService: UserServiceStub; // NEW
class UserServiceStub {
userLogin(email: string, password: string) {
return Promise.resolve([email, password]); // UPDATED
// OR: return Observable.of([email, password]);
}
}
beforeEach(() => {
userService = new UserServiceStub();
TestBed.configureTestingModule({
declarations: [LoginComponent],
imports: [HttpModule, FormsModule, RouterTestingModule],
providers: [
{provide: UserService, useValue: userService} // UPDATED
]
});
service = TestBed.get(UserService);
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should call the service when the sign in button is clicked', () => {
spyOn(userService, 'userLogin').and.callThrough(); // NEW
component.onLoginButtonClick();
expect(service.userLogin).toHaveBeenCalled(); // UPDATED
});
});
You can read more about Jasmine Spies here. The gist is that they allow you to check if a method has been called. You can also check things like what it was called with, what it returned, and so on. There are many ways to use them and they are very powerful. I hope this helped!
Upvotes: 2