Testing component is using the original service and not spying itUnit Testing C CodeWhat is Unit test, Integration Test, Smoke test, Regression Test?How to write a test which expects an Error to be thrown in Jasmine?What's the difference between unit, functional, acceptance, and integration tests?Components and modules exported from shared modules with forRoot option not available in lazy loaded moduleAngular 2 Routing Does Not Work When Deployed to Http ServerAngular 4 ERROR Error: Uncaught (in promise): RangeError: Maximum call stack size exceededAngular testing with keycloack “user is not logged in”error TS2707 : Generic type 'MatDialogRef<T,R>' requiers between 1 and 2 argumentsCore module component and Shared module implementation in angular

Proto-Indo-European (PIE) words with IPA

Which values for voltage divider

Were there any developed countries that became "undeveloped" for reasons other than war?

What pc resources are used when bruteforcing?

Is being an extrovert a necessary condition to be a manager?

Is there a fox people race in D&D 5e?

How to make Flex Markers appear in Logic Pro X?

Team member is vehemently against code formatting

What defines a person who is circumcised "of the heart"?

Is it safe to redirect stdout and stderr to the same file without file descriptor copies?

Illustrating that universal optimality is stronger than sphere packing

Keeping the dodos out of the field

Must every right-inverse of a linear transformation be a linear transformation?

Three knights or knaves, three different hair colors

What is the winged creature on the back of the Mordenkainen's Tome of Foes book?

Why are logically related bit fields in MCU registers often in separate locations

Informal question construction: "Anyone know what...", "Everyone finished?"

What technology is there beyond RAID for disk cluster in a server

Coloring lines in a graph the same color if they are the same length

Singular Integration

Managing heat dissipation in a magic wand

Why does the -OH group in β-naphthol direct the incoming diazonium salt towards the ortho position?

How to become an Editorial board member?

(For training purposes) Are there any openings with rook pawns that are more effective than others (and if so, what are they)?



Testing component is using the original service and not spying it


Unit Testing C CodeWhat is Unit test, Integration Test, Smoke test, Regression Test?How to write a test which expects an Error to be thrown in Jasmine?What's the difference between unit, functional, acceptance, and integration tests?Components and modules exported from shared modules with forRoot option not available in lazy loaded moduleAngular 2 Routing Does Not Work When Deployed to Http ServerAngular 4 ERROR Error: Uncaught (in promise): RangeError: Maximum call stack size exceededAngular testing with keycloack “user is not logged in”error TS2707 : Generic type 'MatDialogRef<T,R>' requiers between 1 and 2 argumentsCore module component and Shared module implementation in angular






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








0















When I test if the button is clicked and it calls the onSignIn() method on the component this test pass.



But when I try to test if the onSignIn() calls signIn() method on the AuthService, the test not pass and call the original service doing a network call.



Here is my code:



sign-in.component.ts



import Component, OnInit from '@angular/core';
import FormBuilder, FormGroup, Validators from '@angular/forms';
import ActivatedRoute, Router from '@angular/router';
import faTimes from '@fortawesome/free-solid-svg-icons';
import AuthService from '../../core';
import AlertService, FormErrorHandler from '../../shared';

@Component(
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.scss']
)
export class SignInComponent implements OnInit
signInForm!: FormGroup;
...

constructor(
private formBuilder: FormBuilder,
private router: Router,
private activatedRoute: ActivatedRoute,
private authService: AuthService,
private alertService: AlertService
)

ngOnInit()
...

...

onSignIn()
...

this.authService
.signIn(this.signInForm.value)
.subscribe(
user =>
this.authService.setSession(user, this.rememberMe.value);
this.router.navigate([this.returnUrl]);
,
error =>
if (error instanceof Object)
FormErrorHandler.errorHandler(this.signInForm, error);
else
this.alertService.error(error);


);




sign-in.module.ts



import NgModule from '@angular/core';
import CommonModule from '@angular/common';
import AuthRoutingModule from './auth-routing.module';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import FormsModule, ReactiveFormsModule from '@angular/forms';
import HttpClientModule from '@angular/common/http';
import SharedModule from '../shared';
import AuthComponent from './auth.component';
import SignInComponent from './sign-in/sign-in.component';
import SignUpComponent from './sign-up/sign-up.component';
import PasswordRecoverComponent from './password-recover/password-recover.component';
import PasswordResetComponent from './password-reset/password-reset.component';

@NgModule(
declarations: [
AuthComponent,
SignInComponent,
SignUpComponent,
PasswordRecoverComponent,
PasswordResetComponent
],
imports: [
CommonModule,
AuthRoutingModule,
SharedModule,
FontAwesomeModule,
ReactiveFormsModule,
FormsModule,
HttpClientModule,
]
)
export class AuthModule


auth.service.ts



import HttpClient from '@angular/common/http';
import Injectable from '@angular/core';
import Router from '@angular/router';
import map from 'rxjs/operators';
import config from '../../../config';
import User from '../../../shared';
import Subject from 'rxjs';

@Injectable( providedIn: 'root' )
export class AuthService
public isAuthenticated = false;
public authStatusSubject = new Subject<boolean>();
public currentUserId = '';
public currentUserToken = '';

get id() return localStorage.getItem('id');

get token() return localStorage.getItem('token');

get expiration() return localStorage.getItem('expires_at');

getAuthStatusSubject() return this.authStatusSubject.asObservable();

constructor(private http: HttpClient, private router: Router)
...

signIn(user: User)
return this.http.post<
message: string;
user: id: string; token: string; expiresAt: string ;
>(`$config.URL/api/auth/login`,
email: user.email,
password: user.password
)
.pipe(map(data => return data.user; ));


setSession(user, rememberMe: boolean)
if (rememberMe)
const expiresAt = new Date(user.expiresAt);
localStorage.setItem('id', user.id);
localStorage.setItem('token', user.token);
localStorage.setItem('expires_at', expiresAt.toUTCString());

this.isAuthenticated = true;
this.authStatusSubject.next(true);
this.currentUserId = user.id;
this.currentUserToken = user.token;

...



The AuthService is provided in the core.module



core.module.ts



import CommonModule from '@angular/common';
import NgModule from '@angular/core';
import RouterModule from '@angular/router';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import NgbModule from '@ng-bootstrap/ng-bootstrap';

import HeaderComponent from './components';
import AuthService, UserService from './services';

@NgModule(
declarations: [ HeaderComponent ],
imports: [
CommonModule,
RouterModule,
FontAwesomeModule,
NgbModule,
],
providers: [
AuthService,
UserService
],
exports: [ HeaderComponent ]
)
export class CoreModule


sign-in.component.spec.ts



import HttpClientTestingModule from '@angular/common/http/testing';
import async, ComponentFixture, TestBed from '@angular/core/testing';
import AbstractControl, FormsModule, ReactiveFormsModule from '@angular/forms';
import By from '@angular/platform-browser';
import RouterTestingModule from '@angular/router/testing';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import AuthService, CoreModule from '../../core';
import SharedModule from '../../shared';
import SignInComponent from './sign-in.component';

describe('SignInComponent', () =>
let signInComponent: SignInComponent;
let fixture: ComponentFixture<SignInComponent>;
let signInButton: any;
let authService: AuthService;
...

beforeEach(async(() =>
TestBed.configureTestingModule(
declarations: [SignInComponent],
imports: [
HttpClientTestingModule,
FormsModule,
ReactiveFormsModule,
RouterTestingModule,
FontAwesomeModule,
CoreModule,
SharedModule
]
)
.compileComponents()
.then(() =>
fixture = TestBed.createComponent(SignInComponent);
signInComponent = fixture.componentInstance;
signInComponent.ngOnInit();

authService = TestBed.get(AuthService);
);
));

beforeEach(() =>
fixture.detectChanges();
);

it('should be created', () =>
expect(signInComponent).toBeTruthy();
);

describe('#form', () =>
describe('#signInButton', () =>
beforeEach(() =>
signInButton = fixture.debugElement.query(By.css('button[type=submit]')).nativeElement;
);

it('should render button for submit form', () =>
expect(signInButton).toBeTruthy();
);

it('should sign in when submited', () =>
spyOn(signInComponent, 'onSignIn');
spyOn(authService, 'signIn');

signInForm.triggerEventHandler('submit', null);

expect(signInComponent.onSignIn).toHaveBeenCalled(); // This test pass
expect(authService.signIn).toHaveBeenCalled(); // This test fails and do a network call.
);
);
);
);









share|improve this question
























  • Don't spy on the component you're testing. Use the TestBed to provide test doubles for its collaborators, not recreate the real app. See e.g. angular.io/guide/testing, blog.jonrshar.pe/2017/Apr/16/async-angular-tests.html

    – jonrsharpe
    Mar 23 at 20:37











  • Thanks for your quick response @jonrsharpe . Spying is the only way I know to know if the component's method has been called or triggered, Why do you say that I should not spy on the component's method? By the way, spying on the component method works, but what does not work for me is spying on the service method and I do not understand why, it should be called once the component method is triggered.

    – Andrea Contreras
    Mar 26 at 1:25












  • I say you shouldn't spy on the component's method because the component is the unit you're testing, and you should test its behaviour not its implementation. The service isn't called because you spy on the component method, too; you don't call through.

    – jonrsharpe
    Mar 26 at 7:12











  • If the call to the service is within the onSignIn() method of the component, this is not part of its behavior, then, I should not test that onSignIn() is called and it invokes a service method, right? I should only test that the component's method is called, not if it is calling the service, right?

    – Andrea Contreras
    Mar 28 at 19:17











  • No that's exactly wrong. You should test that it's calling the service with the right data when the inputs are filled and the button is clicked, what method gets called is an implementation detail you should be free to refactor.

    – jonrsharpe
    Mar 28 at 19:22

















0















When I test if the button is clicked and it calls the onSignIn() method on the component this test pass.



But when I try to test if the onSignIn() calls signIn() method on the AuthService, the test not pass and call the original service doing a network call.



Here is my code:



sign-in.component.ts



import Component, OnInit from '@angular/core';
import FormBuilder, FormGroup, Validators from '@angular/forms';
import ActivatedRoute, Router from '@angular/router';
import faTimes from '@fortawesome/free-solid-svg-icons';
import AuthService from '../../core';
import AlertService, FormErrorHandler from '../../shared';

@Component(
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.scss']
)
export class SignInComponent implements OnInit
signInForm!: FormGroup;
...

constructor(
private formBuilder: FormBuilder,
private router: Router,
private activatedRoute: ActivatedRoute,
private authService: AuthService,
private alertService: AlertService
)

ngOnInit()
...

...

onSignIn()
...

this.authService
.signIn(this.signInForm.value)
.subscribe(
user =>
this.authService.setSession(user, this.rememberMe.value);
this.router.navigate([this.returnUrl]);
,
error =>
if (error instanceof Object)
FormErrorHandler.errorHandler(this.signInForm, error);
else
this.alertService.error(error);


);




sign-in.module.ts



import NgModule from '@angular/core';
import CommonModule from '@angular/common';
import AuthRoutingModule from './auth-routing.module';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import FormsModule, ReactiveFormsModule from '@angular/forms';
import HttpClientModule from '@angular/common/http';
import SharedModule from '../shared';
import AuthComponent from './auth.component';
import SignInComponent from './sign-in/sign-in.component';
import SignUpComponent from './sign-up/sign-up.component';
import PasswordRecoverComponent from './password-recover/password-recover.component';
import PasswordResetComponent from './password-reset/password-reset.component';

@NgModule(
declarations: [
AuthComponent,
SignInComponent,
SignUpComponent,
PasswordRecoverComponent,
PasswordResetComponent
],
imports: [
CommonModule,
AuthRoutingModule,
SharedModule,
FontAwesomeModule,
ReactiveFormsModule,
FormsModule,
HttpClientModule,
]
)
export class AuthModule


auth.service.ts



import HttpClient from '@angular/common/http';
import Injectable from '@angular/core';
import Router from '@angular/router';
import map from 'rxjs/operators';
import config from '../../../config';
import User from '../../../shared';
import Subject from 'rxjs';

@Injectable( providedIn: 'root' )
export class AuthService
public isAuthenticated = false;
public authStatusSubject = new Subject<boolean>();
public currentUserId = '';
public currentUserToken = '';

get id() return localStorage.getItem('id');

get token() return localStorage.getItem('token');

get expiration() return localStorage.getItem('expires_at');

getAuthStatusSubject() return this.authStatusSubject.asObservable();

constructor(private http: HttpClient, private router: Router)
...

signIn(user: User)
return this.http.post<
message: string;
user: id: string; token: string; expiresAt: string ;
>(`$config.URL/api/auth/login`,
email: user.email,
password: user.password
)
.pipe(map(data => return data.user; ));


setSession(user, rememberMe: boolean)
if (rememberMe)
const expiresAt = new Date(user.expiresAt);
localStorage.setItem('id', user.id);
localStorage.setItem('token', user.token);
localStorage.setItem('expires_at', expiresAt.toUTCString());

this.isAuthenticated = true;
this.authStatusSubject.next(true);
this.currentUserId = user.id;
this.currentUserToken = user.token;

...



The AuthService is provided in the core.module



core.module.ts



import CommonModule from '@angular/common';
import NgModule from '@angular/core';
import RouterModule from '@angular/router';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import NgbModule from '@ng-bootstrap/ng-bootstrap';

import HeaderComponent from './components';
import AuthService, UserService from './services';

@NgModule(
declarations: [ HeaderComponent ],
imports: [
CommonModule,
RouterModule,
FontAwesomeModule,
NgbModule,
],
providers: [
AuthService,
UserService
],
exports: [ HeaderComponent ]
)
export class CoreModule


sign-in.component.spec.ts



import HttpClientTestingModule from '@angular/common/http/testing';
import async, ComponentFixture, TestBed from '@angular/core/testing';
import AbstractControl, FormsModule, ReactiveFormsModule from '@angular/forms';
import By from '@angular/platform-browser';
import RouterTestingModule from '@angular/router/testing';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import AuthService, CoreModule from '../../core';
import SharedModule from '../../shared';
import SignInComponent from './sign-in.component';

describe('SignInComponent', () =>
let signInComponent: SignInComponent;
let fixture: ComponentFixture<SignInComponent>;
let signInButton: any;
let authService: AuthService;
...

beforeEach(async(() =>
TestBed.configureTestingModule(
declarations: [SignInComponent],
imports: [
HttpClientTestingModule,
FormsModule,
ReactiveFormsModule,
RouterTestingModule,
FontAwesomeModule,
CoreModule,
SharedModule
]
)
.compileComponents()
.then(() =>
fixture = TestBed.createComponent(SignInComponent);
signInComponent = fixture.componentInstance;
signInComponent.ngOnInit();

authService = TestBed.get(AuthService);
);
));

beforeEach(() =>
fixture.detectChanges();
);

it('should be created', () =>
expect(signInComponent).toBeTruthy();
);

describe('#form', () =>
describe('#signInButton', () =>
beforeEach(() =>
signInButton = fixture.debugElement.query(By.css('button[type=submit]')).nativeElement;
);

it('should render button for submit form', () =>
expect(signInButton).toBeTruthy();
);

it('should sign in when submited', () =>
spyOn(signInComponent, 'onSignIn');
spyOn(authService, 'signIn');

signInForm.triggerEventHandler('submit', null);

expect(signInComponent.onSignIn).toHaveBeenCalled(); // This test pass
expect(authService.signIn).toHaveBeenCalled(); // This test fails and do a network call.
);
);
);
);









share|improve this question
























  • Don't spy on the component you're testing. Use the TestBed to provide test doubles for its collaborators, not recreate the real app. See e.g. angular.io/guide/testing, blog.jonrshar.pe/2017/Apr/16/async-angular-tests.html

    – jonrsharpe
    Mar 23 at 20:37











  • Thanks for your quick response @jonrsharpe . Spying is the only way I know to know if the component's method has been called or triggered, Why do you say that I should not spy on the component's method? By the way, spying on the component method works, but what does not work for me is spying on the service method and I do not understand why, it should be called once the component method is triggered.

    – Andrea Contreras
    Mar 26 at 1:25












  • I say you shouldn't spy on the component's method because the component is the unit you're testing, and you should test its behaviour not its implementation. The service isn't called because you spy on the component method, too; you don't call through.

    – jonrsharpe
    Mar 26 at 7:12











  • If the call to the service is within the onSignIn() method of the component, this is not part of its behavior, then, I should not test that onSignIn() is called and it invokes a service method, right? I should only test that the component's method is called, not if it is calling the service, right?

    – Andrea Contreras
    Mar 28 at 19:17











  • No that's exactly wrong. You should test that it's calling the service with the right data when the inputs are filled and the button is clicked, what method gets called is an implementation detail you should be free to refactor.

    – jonrsharpe
    Mar 28 at 19:22













0












0








0


1






When I test if the button is clicked and it calls the onSignIn() method on the component this test pass.



But when I try to test if the onSignIn() calls signIn() method on the AuthService, the test not pass and call the original service doing a network call.



Here is my code:



sign-in.component.ts



import Component, OnInit from '@angular/core';
import FormBuilder, FormGroup, Validators from '@angular/forms';
import ActivatedRoute, Router from '@angular/router';
import faTimes from '@fortawesome/free-solid-svg-icons';
import AuthService from '../../core';
import AlertService, FormErrorHandler from '../../shared';

@Component(
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.scss']
)
export class SignInComponent implements OnInit
signInForm!: FormGroup;
...

constructor(
private formBuilder: FormBuilder,
private router: Router,
private activatedRoute: ActivatedRoute,
private authService: AuthService,
private alertService: AlertService
)

ngOnInit()
...

...

onSignIn()
...

this.authService
.signIn(this.signInForm.value)
.subscribe(
user =>
this.authService.setSession(user, this.rememberMe.value);
this.router.navigate([this.returnUrl]);
,
error =>
if (error instanceof Object)
FormErrorHandler.errorHandler(this.signInForm, error);
else
this.alertService.error(error);


);




sign-in.module.ts



import NgModule from '@angular/core';
import CommonModule from '@angular/common';
import AuthRoutingModule from './auth-routing.module';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import FormsModule, ReactiveFormsModule from '@angular/forms';
import HttpClientModule from '@angular/common/http';
import SharedModule from '../shared';
import AuthComponent from './auth.component';
import SignInComponent from './sign-in/sign-in.component';
import SignUpComponent from './sign-up/sign-up.component';
import PasswordRecoverComponent from './password-recover/password-recover.component';
import PasswordResetComponent from './password-reset/password-reset.component';

@NgModule(
declarations: [
AuthComponent,
SignInComponent,
SignUpComponent,
PasswordRecoverComponent,
PasswordResetComponent
],
imports: [
CommonModule,
AuthRoutingModule,
SharedModule,
FontAwesomeModule,
ReactiveFormsModule,
FormsModule,
HttpClientModule,
]
)
export class AuthModule


auth.service.ts



import HttpClient from '@angular/common/http';
import Injectable from '@angular/core';
import Router from '@angular/router';
import map from 'rxjs/operators';
import config from '../../../config';
import User from '../../../shared';
import Subject from 'rxjs';

@Injectable( providedIn: 'root' )
export class AuthService
public isAuthenticated = false;
public authStatusSubject = new Subject<boolean>();
public currentUserId = '';
public currentUserToken = '';

get id() return localStorage.getItem('id');

get token() return localStorage.getItem('token');

get expiration() return localStorage.getItem('expires_at');

getAuthStatusSubject() return this.authStatusSubject.asObservable();

constructor(private http: HttpClient, private router: Router)
...

signIn(user: User)
return this.http.post<
message: string;
user: id: string; token: string; expiresAt: string ;
>(`$config.URL/api/auth/login`,
email: user.email,
password: user.password
)
.pipe(map(data => return data.user; ));


setSession(user, rememberMe: boolean)
if (rememberMe)
const expiresAt = new Date(user.expiresAt);
localStorage.setItem('id', user.id);
localStorage.setItem('token', user.token);
localStorage.setItem('expires_at', expiresAt.toUTCString());

this.isAuthenticated = true;
this.authStatusSubject.next(true);
this.currentUserId = user.id;
this.currentUserToken = user.token;

...



The AuthService is provided in the core.module



core.module.ts



import CommonModule from '@angular/common';
import NgModule from '@angular/core';
import RouterModule from '@angular/router';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import NgbModule from '@ng-bootstrap/ng-bootstrap';

import HeaderComponent from './components';
import AuthService, UserService from './services';

@NgModule(
declarations: [ HeaderComponent ],
imports: [
CommonModule,
RouterModule,
FontAwesomeModule,
NgbModule,
],
providers: [
AuthService,
UserService
],
exports: [ HeaderComponent ]
)
export class CoreModule


sign-in.component.spec.ts



import HttpClientTestingModule from '@angular/common/http/testing';
import async, ComponentFixture, TestBed from '@angular/core/testing';
import AbstractControl, FormsModule, ReactiveFormsModule from '@angular/forms';
import By from '@angular/platform-browser';
import RouterTestingModule from '@angular/router/testing';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import AuthService, CoreModule from '../../core';
import SharedModule from '../../shared';
import SignInComponent from './sign-in.component';

describe('SignInComponent', () =>
let signInComponent: SignInComponent;
let fixture: ComponentFixture<SignInComponent>;
let signInButton: any;
let authService: AuthService;
...

beforeEach(async(() =>
TestBed.configureTestingModule(
declarations: [SignInComponent],
imports: [
HttpClientTestingModule,
FormsModule,
ReactiveFormsModule,
RouterTestingModule,
FontAwesomeModule,
CoreModule,
SharedModule
]
)
.compileComponents()
.then(() =>
fixture = TestBed.createComponent(SignInComponent);
signInComponent = fixture.componentInstance;
signInComponent.ngOnInit();

authService = TestBed.get(AuthService);
);
));

beforeEach(() =>
fixture.detectChanges();
);

it('should be created', () =>
expect(signInComponent).toBeTruthy();
);

describe('#form', () =>
describe('#signInButton', () =>
beforeEach(() =>
signInButton = fixture.debugElement.query(By.css('button[type=submit]')).nativeElement;
);

it('should render button for submit form', () =>
expect(signInButton).toBeTruthy();
);

it('should sign in when submited', () =>
spyOn(signInComponent, 'onSignIn');
spyOn(authService, 'signIn');

signInForm.triggerEventHandler('submit', null);

expect(signInComponent.onSignIn).toHaveBeenCalled(); // This test pass
expect(authService.signIn).toHaveBeenCalled(); // This test fails and do a network call.
);
);
);
);









share|improve this question
















When I test if the button is clicked and it calls the onSignIn() method on the component this test pass.



But when I try to test if the onSignIn() calls signIn() method on the AuthService, the test not pass and call the original service doing a network call.



Here is my code:



sign-in.component.ts



import Component, OnInit from '@angular/core';
import FormBuilder, FormGroup, Validators from '@angular/forms';
import ActivatedRoute, Router from '@angular/router';
import faTimes from '@fortawesome/free-solid-svg-icons';
import AuthService from '../../core';
import AlertService, FormErrorHandler from '../../shared';

@Component(
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.scss']
)
export class SignInComponent implements OnInit
signInForm!: FormGroup;
...

constructor(
private formBuilder: FormBuilder,
private router: Router,
private activatedRoute: ActivatedRoute,
private authService: AuthService,
private alertService: AlertService
)

ngOnInit()
...

...

onSignIn()
...

this.authService
.signIn(this.signInForm.value)
.subscribe(
user =>
this.authService.setSession(user, this.rememberMe.value);
this.router.navigate([this.returnUrl]);
,
error =>
if (error instanceof Object)
FormErrorHandler.errorHandler(this.signInForm, error);
else
this.alertService.error(error);


);




sign-in.module.ts



import NgModule from '@angular/core';
import CommonModule from '@angular/common';
import AuthRoutingModule from './auth-routing.module';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import FormsModule, ReactiveFormsModule from '@angular/forms';
import HttpClientModule from '@angular/common/http';
import SharedModule from '../shared';
import AuthComponent from './auth.component';
import SignInComponent from './sign-in/sign-in.component';
import SignUpComponent from './sign-up/sign-up.component';
import PasswordRecoverComponent from './password-recover/password-recover.component';
import PasswordResetComponent from './password-reset/password-reset.component';

@NgModule(
declarations: [
AuthComponent,
SignInComponent,
SignUpComponent,
PasswordRecoverComponent,
PasswordResetComponent
],
imports: [
CommonModule,
AuthRoutingModule,
SharedModule,
FontAwesomeModule,
ReactiveFormsModule,
FormsModule,
HttpClientModule,
]
)
export class AuthModule


auth.service.ts



import HttpClient from '@angular/common/http';
import Injectable from '@angular/core';
import Router from '@angular/router';
import map from 'rxjs/operators';
import config from '../../../config';
import User from '../../../shared';
import Subject from 'rxjs';

@Injectable( providedIn: 'root' )
export class AuthService
public isAuthenticated = false;
public authStatusSubject = new Subject<boolean>();
public currentUserId = '';
public currentUserToken = '';

get id() return localStorage.getItem('id');

get token() return localStorage.getItem('token');

get expiration() return localStorage.getItem('expires_at');

getAuthStatusSubject() return this.authStatusSubject.asObservable();

constructor(private http: HttpClient, private router: Router)
...

signIn(user: User)
return this.http.post<
message: string;
user: id: string; token: string; expiresAt: string ;
>(`$config.URL/api/auth/login`,
email: user.email,
password: user.password
)
.pipe(map(data => return data.user; ));


setSession(user, rememberMe: boolean)
if (rememberMe)
const expiresAt = new Date(user.expiresAt);
localStorage.setItem('id', user.id);
localStorage.setItem('token', user.token);
localStorage.setItem('expires_at', expiresAt.toUTCString());

this.isAuthenticated = true;
this.authStatusSubject.next(true);
this.currentUserId = user.id;
this.currentUserToken = user.token;

...



The AuthService is provided in the core.module



core.module.ts



import CommonModule from '@angular/common';
import NgModule from '@angular/core';
import RouterModule from '@angular/router';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import NgbModule from '@ng-bootstrap/ng-bootstrap';

import HeaderComponent from './components';
import AuthService, UserService from './services';

@NgModule(
declarations: [ HeaderComponent ],
imports: [
CommonModule,
RouterModule,
FontAwesomeModule,
NgbModule,
],
providers: [
AuthService,
UserService
],
exports: [ HeaderComponent ]
)
export class CoreModule


sign-in.component.spec.ts



import HttpClientTestingModule from '@angular/common/http/testing';
import async, ComponentFixture, TestBed from '@angular/core/testing';
import AbstractControl, FormsModule, ReactiveFormsModule from '@angular/forms';
import By from '@angular/platform-browser';
import RouterTestingModule from '@angular/router/testing';
import FontAwesomeModule from '@fortawesome/angular-fontawesome';
import AuthService, CoreModule from '../../core';
import SharedModule from '../../shared';
import SignInComponent from './sign-in.component';

describe('SignInComponent', () =>
let signInComponent: SignInComponent;
let fixture: ComponentFixture<SignInComponent>;
let signInButton: any;
let authService: AuthService;
...

beforeEach(async(() =>
TestBed.configureTestingModule(
declarations: [SignInComponent],
imports: [
HttpClientTestingModule,
FormsModule,
ReactiveFormsModule,
RouterTestingModule,
FontAwesomeModule,
CoreModule,
SharedModule
]
)
.compileComponents()
.then(() =>
fixture = TestBed.createComponent(SignInComponent);
signInComponent = fixture.componentInstance;
signInComponent.ngOnInit();

authService = TestBed.get(AuthService);
);
));

beforeEach(() =>
fixture.detectChanges();
);

it('should be created', () =>
expect(signInComponent).toBeTruthy();
);

describe('#form', () =>
describe('#signInButton', () =>
beforeEach(() =>
signInButton = fixture.debugElement.query(By.css('button[type=submit]')).nativeElement;
);

it('should render button for submit form', () =>
expect(signInButton).toBeTruthy();
);

it('should sign in when submited', () =>
spyOn(signInComponent, 'onSignIn');
spyOn(authService, 'signIn');

signInForm.triggerEventHandler('submit', null);

expect(signInComponent.onSignIn).toHaveBeenCalled(); // This test pass
expect(authService.signIn).toHaveBeenCalled(); // This test fails and do a network call.
);
);
);
);






angular testing jasmine karma-runner






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 23 at 20:35









jonrsharpe

79.9k11115232




79.9k11115232










asked Mar 23 at 20:08









Andrea ContrerasAndrea Contreras

11




11












  • Don't spy on the component you're testing. Use the TestBed to provide test doubles for its collaborators, not recreate the real app. See e.g. angular.io/guide/testing, blog.jonrshar.pe/2017/Apr/16/async-angular-tests.html

    – jonrsharpe
    Mar 23 at 20:37











  • Thanks for your quick response @jonrsharpe . Spying is the only way I know to know if the component's method has been called or triggered, Why do you say that I should not spy on the component's method? By the way, spying on the component method works, but what does not work for me is spying on the service method and I do not understand why, it should be called once the component method is triggered.

    – Andrea Contreras
    Mar 26 at 1:25












  • I say you shouldn't spy on the component's method because the component is the unit you're testing, and you should test its behaviour not its implementation. The service isn't called because you spy on the component method, too; you don't call through.

    – jonrsharpe
    Mar 26 at 7:12











  • If the call to the service is within the onSignIn() method of the component, this is not part of its behavior, then, I should not test that onSignIn() is called and it invokes a service method, right? I should only test that the component's method is called, not if it is calling the service, right?

    – Andrea Contreras
    Mar 28 at 19:17











  • No that's exactly wrong. You should test that it's calling the service with the right data when the inputs are filled and the button is clicked, what method gets called is an implementation detail you should be free to refactor.

    – jonrsharpe
    Mar 28 at 19:22

















  • Don't spy on the component you're testing. Use the TestBed to provide test doubles for its collaborators, not recreate the real app. See e.g. angular.io/guide/testing, blog.jonrshar.pe/2017/Apr/16/async-angular-tests.html

    – jonrsharpe
    Mar 23 at 20:37











  • Thanks for your quick response @jonrsharpe . Spying is the only way I know to know if the component's method has been called or triggered, Why do you say that I should not spy on the component's method? By the way, spying on the component method works, but what does not work for me is spying on the service method and I do not understand why, it should be called once the component method is triggered.

    – Andrea Contreras
    Mar 26 at 1:25












  • I say you shouldn't spy on the component's method because the component is the unit you're testing, and you should test its behaviour not its implementation. The service isn't called because you spy on the component method, too; you don't call through.

    – jonrsharpe
    Mar 26 at 7:12











  • If the call to the service is within the onSignIn() method of the component, this is not part of its behavior, then, I should not test that onSignIn() is called and it invokes a service method, right? I should only test that the component's method is called, not if it is calling the service, right?

    – Andrea Contreras
    Mar 28 at 19:17











  • No that's exactly wrong. You should test that it's calling the service with the right data when the inputs are filled and the button is clicked, what method gets called is an implementation detail you should be free to refactor.

    – jonrsharpe
    Mar 28 at 19:22
















Don't spy on the component you're testing. Use the TestBed to provide test doubles for its collaborators, not recreate the real app. See e.g. angular.io/guide/testing, blog.jonrshar.pe/2017/Apr/16/async-angular-tests.html

– jonrsharpe
Mar 23 at 20:37





Don't spy on the component you're testing. Use the TestBed to provide test doubles for its collaborators, not recreate the real app. See e.g. angular.io/guide/testing, blog.jonrshar.pe/2017/Apr/16/async-angular-tests.html

– jonrsharpe
Mar 23 at 20:37













Thanks for your quick response @jonrsharpe . Spying is the only way I know to know if the component's method has been called or triggered, Why do you say that I should not spy on the component's method? By the way, spying on the component method works, but what does not work for me is spying on the service method and I do not understand why, it should be called once the component method is triggered.

– Andrea Contreras
Mar 26 at 1:25






Thanks for your quick response @jonrsharpe . Spying is the only way I know to know if the component's method has been called or triggered, Why do you say that I should not spy on the component's method? By the way, spying on the component method works, but what does not work for me is spying on the service method and I do not understand why, it should be called once the component method is triggered.

– Andrea Contreras
Mar 26 at 1:25














I say you shouldn't spy on the component's method because the component is the unit you're testing, and you should test its behaviour not its implementation. The service isn't called because you spy on the component method, too; you don't call through.

– jonrsharpe
Mar 26 at 7:12





I say you shouldn't spy on the component's method because the component is the unit you're testing, and you should test its behaviour not its implementation. The service isn't called because you spy on the component method, too; you don't call through.

– jonrsharpe
Mar 26 at 7:12













If the call to the service is within the onSignIn() method of the component, this is not part of its behavior, then, I should not test that onSignIn() is called and it invokes a service method, right? I should only test that the component's method is called, not if it is calling the service, right?

– Andrea Contreras
Mar 28 at 19:17





If the call to the service is within the onSignIn() method of the component, this is not part of its behavior, then, I should not test that onSignIn() is called and it invokes a service method, right? I should only test that the component's method is called, not if it is calling the service, right?

– Andrea Contreras
Mar 28 at 19:17













No that's exactly wrong. You should test that it's calling the service with the right data when the inputs are filled and the button is clicked, what method gets called is an implementation detail you should be free to refactor.

– jonrsharpe
Mar 28 at 19:22





No that's exactly wrong. You should test that it's calling the service with the right data when the inputs are filled and the button is clicked, what method gets called is an implementation detail you should be free to refactor.

– jonrsharpe
Mar 28 at 19:22












0






active

oldest

votes












Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55317917%2ftesting-component-is-using-the-original-service-and-not-spying-it%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55317917%2ftesting-component-is-using-the-original-service-and-not-spying-it%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

용인 삼성생명 블루밍스 목차 통계 역대 감독 선수단 응원단 경기장 같이 보기 외부 링크 둘러보기 메뉴samsungblueminx.comeh선수 명단용인 삼성생명 블루밍스용인 삼성생명 블루밍스ehsamsungblueminx.comeheheheh

155 수학 과학 기타 둘러보기 메뉴eh추가해eh문서를 완성해