SpyOn 无法正常工作 - Angular
SpyOn not working properly - Angular
当我 运行 我的规格时,我的集成测试失败表明我的 spyOn 用于 Auth0 服务 auth.authenticated () 没有设置正确的 return 值。基本上,这个规范应该 returning 一个 truthy 值 (id_token) 以便 Log Out 按钮被显示。由于它仍然显示 Log In 按钮,我假设空值是固定的,而不是被设置为 AuthResponse 变量中的字符串。
我的设置中是否遗漏了什么?任何帮助将不胜感激。
//navbar.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'afn-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
constructor(private auth: AuthService) { }
ngOnInit() {
}
}
//navbar.component.spec.ts
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NavbarComponent } from './navbar.component';
import { AuthService } from '../auth.service';
describe('NavbarComponent', () => {
let component: NavbarComponent;
let navbar: NavbarComponent;
let fixture: ComponentFixture<NavbarComponent>;
let auth: AuthService;
let authResponse: string;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ NavbarComponent ],
providers: [ AuthService ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
auth = new AuthService();
spyOn(auth, 'authenticated').and.returnValue(authResponse);
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('Unauthenticated user', () => {
beforeEach(() => {
authResponse = null;
navbar = fixture.debugElement.componentInstance;
});
it('should should display "Log In" button', async(() => {
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('button').textContent).toContain('Log In');
}));
it('should receive a falsy response from auth.authenticated', async(() => {
navbar.ngOnInit();
expect(auth.authenticated()).toBeFalsy();
}));
});
describe('Authenticated user', () => {
beforeEach(() => {
authResponse = '23kjsfdi723bsai7234dfsfghfg';
navbar = fixture.debugElement.componentInstance;
});
it('should display "Log Out" button', async(() => {
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('button').textContent).toContain('Log Out');
}));
it('should receive a truthy response from auth.authenticated', async(() => {
navbar.ngOnInit();
expect(auth.authenticated()).toBeTruthy();
}));
});
});
导航栏组件的模板
//navbar.component.html
<div class="navbar-header">
<a class="navbar-brand" href="#">Auth0 - Angular 2</a>
<button class="btn btn-primary btn-margin" (click)="auth.login()" *ngIf="!auth.authenticated()">Log In</button>
<button class="btn btn-primary btn-margin" (click)="auth.logout()" *ngIf="auth.authenticated()">Log Out</button>
</div>
Auth0 服务
//auth.service.ts
import { Injectable } from '@angular/core';
import { tokenNotExpired } from 'angular2-jwt';
import Auth0Lock from 'auth0-lock';
@Injectable()
export class AuthService {
// Configure Auth0
lock = new Auth0Lock('hcDsjVxfeZuAVWg39KIWFXV63n8DjHli', 'afn.auth0.com', {});
constructor() {
// Add callback for lock `authenticated` event
this.lock.on('authenticated', (authResult) => {
localStorage.setItem('id_token', authResult.idToken);
});
}
public login() {
// Call the show method to display the widget.
this.lock.show();
}
public authenticated() {
// Check if there's an unexpired JWT
// This searches for an item in localStorage with key == 'id_token'
return tokenNotExpired('id_token');
}
public logout() {
// Remove token from localStorage
localStorage.removeItem('id_token');
}
}
从@JBNizet 得到提示后,我没有从 TestBed 实例化 AuthService,我决定为每个响应制作一个单独的 spyOn。虽然它看起来不干燥,但它确实有效。
这是 navbar.component.spec.ts 的解决方案:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NavbarComponent } from './navbar.component';
import { AuthService } from '../auth.service';
describe('NavbarComponent', () => {
let component: NavbarComponent;
let navbar: NavbarComponent;
let fixture: ComponentFixture<NavbarComponent>;
let auth: AuthService;
let falsyResponse = null;
let truthyResponse = '23kjsfdi723bsai7234dfsfghfg';
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ NavbarComponent ],
providers: [ AuthService ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
auth = TestBed.get(AuthService);
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('Unauthenticated user', () => {
beforeEach(() => {
spyOn(auth, 'authenticated').and.returnValue(falsyResponse);
navbar = fixture.debugElement.componentInstance;
});
it('should receive a falsy response from auth.authenticated', async(() => {
navbar.ngOnInit();
expect(auth.authenticated()).toBeFalsy();
}));
it('should should display "Log In" button', async(() => {
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('button').textContent).toContain('Log In');
}));
});
describe('Authenticated user', () => {
beforeEach(() => {
spyOn(auth, 'authenticated').and.returnValue(truthyResponse);
navbar = fixture.debugElement.componentInstance;
});
it('should receive a truthy response from auth.authenticated', async(() => {
navbar.ngOnInit();
expect(auth.authenticated()).toBeTruthy();
}));
it('should display "Log Out" button', async(() => {
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('button').textContent).toContain('Log Out');
}));
});
});
当我 运行 我的规格时,我的集成测试失败表明我的 spyOn 用于 Auth0 服务 auth.authenticated () 没有设置正确的 return 值。基本上,这个规范应该 returning 一个 truthy 值 (id_token) 以便 Log Out 按钮被显示。由于它仍然显示 Log In 按钮,我假设空值是固定的,而不是被设置为 AuthResponse 变量中的字符串。
我的设置中是否遗漏了什么?任何帮助将不胜感激。
//navbar.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'afn-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
constructor(private auth: AuthService) { }
ngOnInit() {
}
}
//navbar.component.spec.ts
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NavbarComponent } from './navbar.component';
import { AuthService } from '../auth.service';
describe('NavbarComponent', () => {
let component: NavbarComponent;
let navbar: NavbarComponent;
let fixture: ComponentFixture<NavbarComponent>;
let auth: AuthService;
let authResponse: string;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ NavbarComponent ],
providers: [ AuthService ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
auth = new AuthService();
spyOn(auth, 'authenticated').and.returnValue(authResponse);
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('Unauthenticated user', () => {
beforeEach(() => {
authResponse = null;
navbar = fixture.debugElement.componentInstance;
});
it('should should display "Log In" button', async(() => {
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('button').textContent).toContain('Log In');
}));
it('should receive a falsy response from auth.authenticated', async(() => {
navbar.ngOnInit();
expect(auth.authenticated()).toBeFalsy();
}));
});
describe('Authenticated user', () => {
beforeEach(() => {
authResponse = '23kjsfdi723bsai7234dfsfghfg';
navbar = fixture.debugElement.componentInstance;
});
it('should display "Log Out" button', async(() => {
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('button').textContent).toContain('Log Out');
}));
it('should receive a truthy response from auth.authenticated', async(() => {
navbar.ngOnInit();
expect(auth.authenticated()).toBeTruthy();
}));
});
});
导航栏组件的模板
//navbar.component.html
<div class="navbar-header">
<a class="navbar-brand" href="#">Auth0 - Angular 2</a>
<button class="btn btn-primary btn-margin" (click)="auth.login()" *ngIf="!auth.authenticated()">Log In</button>
<button class="btn btn-primary btn-margin" (click)="auth.logout()" *ngIf="auth.authenticated()">Log Out</button>
</div>
Auth0 服务
//auth.service.ts
import { Injectable } from '@angular/core';
import { tokenNotExpired } from 'angular2-jwt';
import Auth0Lock from 'auth0-lock';
@Injectable()
export class AuthService {
// Configure Auth0
lock = new Auth0Lock('hcDsjVxfeZuAVWg39KIWFXV63n8DjHli', 'afn.auth0.com', {});
constructor() {
// Add callback for lock `authenticated` event
this.lock.on('authenticated', (authResult) => {
localStorage.setItem('id_token', authResult.idToken);
});
}
public login() {
// Call the show method to display the widget.
this.lock.show();
}
public authenticated() {
// Check if there's an unexpired JWT
// This searches for an item in localStorage with key == 'id_token'
return tokenNotExpired('id_token');
}
public logout() {
// Remove token from localStorage
localStorage.removeItem('id_token');
}
}
从@JBNizet 得到提示后,我没有从 TestBed 实例化 AuthService,我决定为每个响应制作一个单独的 spyOn。虽然它看起来不干燥,但它确实有效。
这是 navbar.component.spec.ts 的解决方案:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NavbarComponent } from './navbar.component';
import { AuthService } from '../auth.service';
describe('NavbarComponent', () => {
let component: NavbarComponent;
let navbar: NavbarComponent;
let fixture: ComponentFixture<NavbarComponent>;
let auth: AuthService;
let falsyResponse = null;
let truthyResponse = '23kjsfdi723bsai7234dfsfghfg';
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ NavbarComponent ],
providers: [ AuthService ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(() => {
auth = TestBed.get(AuthService);
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('Unauthenticated user', () => {
beforeEach(() => {
spyOn(auth, 'authenticated').and.returnValue(falsyResponse);
navbar = fixture.debugElement.componentInstance;
});
it('should receive a falsy response from auth.authenticated', async(() => {
navbar.ngOnInit();
expect(auth.authenticated()).toBeFalsy();
}));
it('should should display "Log In" button', async(() => {
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('button').textContent).toContain('Log In');
}));
});
describe('Authenticated user', () => {
beforeEach(() => {
spyOn(auth, 'authenticated').and.returnValue(truthyResponse);
navbar = fixture.debugElement.componentInstance;
});
it('should receive a truthy response from auth.authenticated', async(() => {
navbar.ngOnInit();
expect(auth.authenticated()).toBeTruthy();
}));
it('should display "Log Out" button', async(() => {
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('button').textContent).toContain('Log Out');
}));
});
});