typescript - Angular 2 enhetstest tjeneste stub verdi endres ikke?
Jeg jobber meg gjennom Angular 2 testingseksempler her https://angular.io/docs/ts/latest/guide/testing.html
Velkomstkomponent
import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app-welcome',
template: '<h3 class="welcome" ><i>{{welcome}}</i></h3>'
})
export class WelcomeComponent implements OnInit {
welcome = '-- not initialized yet --';
constructor(private userService: UserService) {
}
ngOnInit(): void {
this.welcome = this.userService.isLoggedIn ?
'Welcome, ' + this.userService.user.name :
'Please log in.';
}
}
Testspesifikasjon
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { WelcomeComponent } from './welcome.component';
import { UserService } from './user.service';
describe('WelcomeComponent', () => {
let component: WelcomeComponent;
let fixture: ComponentFixture<WelcomeComponent>;
let de: DebugElement;
let el: HTMLElement;
let userServiceStub: UserService;
let userService:UserService;
beforeEach(async(() => {
// Declare stub UserService for test purposes
let userServiceStub = {
isLoggedIn: true,
user: { name: 'Test User'}
};
TestBed.configureTestingModule({
declarations: [ WelcomeComponent ],
providers: [ {provide: UserService, useValue: userServiceStub } ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(WelcomeComponent);
component = fixture.componentInstance;
//userService = TestBed.get(UserService);
userService = fixture.debugElement.injector.get(UserService);
// get the "welcome" element by CSS selector (e.g., by class name)
de = fixture.debugElement.query(By.css('.welcome'));
el = de.nativeElement;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should welcome the user', () => {
fixture.detectChanges();
const content = el.textContent;
expect(content).toContain('Welcome', '"Welcome ..."');
expect(content).toContain('Test User', 'expected name');
});
it('should welcome "Bubba"', () => {
userService.user.name = 'Bubba';
fixture.detectChanges();
expect(el.textContent).toContain('Bubba');
});
it('should request login if not logged in', () => {
userService.isLoggedIn = false;
fixture.detectChanges();
const content = el.textContent;
expect(content).not.toContain('Welcome', 'not welcomed');
expect(content).toMatch(/log in/i, '"log in"');
});
});
De siste 2 it()-testene feilet fordi verdiene til tjenestestubben ikke endret seg etter
userService.user.name = 'Bubba';
fixture.detectChanges();
og
userService.isLoggedIn = false;
fixture.detectChanges();
Noen ide om hvorfor Angular-testmodulen ikke klarte å oppdage endring?
Oppdatering
Jeg fant det. fixture.detectChanges() utløser ngOnInit(). fixture.detectChanges() i beforeEach() er synderen. Fordi den har initialisert komponenten, vil fixture.detectChanges() i it() ikke initialisere komponenten igjen. Så ved å fjerne fixture.detectChanges() fra beforeEach() vil fixture.detectChanges() i it() få sjansen til å utløse ngOnInit() og alle tester vil passere.
beforeEach(() => {
fixture = TestBed.createComponent(WelcomeComponent);
component = fixture.componentInstance;
//userService = TestBed.get(UserService);
userService = fixture.debugElement.injector.get(UserService);
// get the "welcome" element by CSS selector (e.g., by class name)
de = fixture.debugElement.query(By.css('.welcome'));
el = de.nativeElement;
// fixture.detectChanges(); // this is the culprit.
});
Svar #1
Prøv å initialisere tjenesten din på din "den"
it('should welcome "Bubba"' , inject([UserService], (userService: UserService) => {
userService.user.name = 'Bubba';
fixture.detectChanges();
expect(el.textContent).toContain('Bubba');
}));
Svar #2
Her er løsningen.
welcome.component.spec.ts
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { WelcomeComponent } from './welcome.component';
import { UserService } from './user.service';
describe('WelcomeComponent', () => {
let component: WelcomeComponent;
let fixture: ComponentFixture<WelcomeComponent>;
let de: DebugElement;
let el: HTMLElement;
let userServiceStub: UserService;
let userService:UserService;
beforeEach(async(() => {
// Declare stub UserService for test purposes
let userServiceStub = {
isLoggedIn: true,
user: { name: 'Test User'}
};
TestBed.configureTestingModule({
declarations: [ WelcomeComponent ],
providers: [ {provide: UserService, useValue: userServiceStub } ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(WelcomeComponent);
component = fixture.componentInstance;
// UserService from the root injector
//userService = TestBed.get(UserService);
userService = fixture.debugElement.injector.get(UserService);
// get the "welcome" element by CSS selector (e.g., by class name)
de = fixture.debugElement.query(By.css('.welcome'));
el = de.nativeElement;
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should welcome the user', () => {
fixture.detectChanges();
const content = el.textContent;
expect(content).toContain('Welcome', '"Welcome ..."');
expect(content).toContain('Test User', 'expected name');
});
it('should welcome "Bubba"', () => {
userService.user.name = 'Bubba';
fixture.detectChanges();
expect(el.textContent).toContain('Bubba');
});
it('should request login if not logged in', () => {
userService.isLoggedIn = false;
fixture.detectChanges();
const content = el.textContent;
expect(content).not.toContain('Welcome', 'not welcomed');
expect(content).toMatch(/log in/i, '"log in"');
});
});
