代碼以下:css
@Injectable()
export class ValueService {
value:string;
constructor() { }
getValue() { return this.value}
}
複製代碼
測試用例以下:前端
//直接new service 實例
let service: ValueService;
beforeEach(() => { service = new ValueService(); });
it('#getValue should return real value', () => {
expect(service.getValue()).toBe('real value');
});
//or
//直接獲取服務實例進行測試,經過調用服務,校驗邏輯
let service: ValueService;
beforeEach(() => {
TestBed.configureTestingModule({ providers: [ValueService] }); //等效於useClass
});
it('should use ValueService', () => {
service = TestBed.get(ValueService);
expect(service.getValue()).toBe('real value');
});
複製代碼
代碼以下:ajax
@Component({
selector: 'lightswitch-comp',
template: `
<button (click)="clicked()">Click me!</button>
<span>{{message}}</span>`
})
export class LightswitchComponent {
isOn = false;
clicked() { this.isOn = !this.isOn; }
get message() { return `The light is ${this.isOn ? 'On' : 'Off'}`; }
}
複製代碼
測試代碼以下:bash
//直接new
it('#clicked() should set #message to "is on"', () => {
const comp = new LightswitchComponent();
expect(comp.message).toMatch(/is off/i, 'off at first');
comp.clicked();
expect(comp.message).toMatch(/is on/i, 'on after clicked');
});
//獲取組件實例,交給框架建立new
let comp:LightswitchComponent;
beforeEach(() => {
TestBed.configureTestingModule({
// provide the component-under-test and dependent service
providers: [
LightswitchComponent,
]
});
// inject both the component and the dependent service.
comp = TestBed.get(LightswitchComponent);
});
it('#clicked() should set #message to "is on"', () => {
const comp = new LightswitchComponent();
expect(comp.message).toMatch(/is off/i, 'off at first');
comp.clicked();
expect(comp.message).toMatch(/is on/i, 'on after clicked');
});
複製代碼
代碼以下:框架
@Injectable()
export class MasterService {
constructor(private valueService: ValueService) { }
getValue() { return this.valueService.getValue(); }
}
複製代碼
測試以下:dom
let masterService: MasterService;
let valueServiceSpy: jasmine.SpyObj<ValueService>;
beforeEach(() => {
const spy = jasmine.createSpyObj('ValueService', ['getValue']);
TestBed.configureTestingModule({
// Provide both the service-to-test and its (spy) dependency
providers: [
MasterService,
//注入服務,mock提供依賴服務的支持,完成MasterService實例建立
{ provide: ValueService, useValue: spy }
]
});
// Inject both the service-to-test and its (spy) dependency
masterService = TestBed.get(MasterService);
valueServiceSpy = TestBed.get(ValueService);
});
複製代碼
it('#getValue should return stubbed value from a spy', () => {
const stubValue = 'stub value';
valueServiceSpy.getValue.and.returnValue(stubValue);
expect(masterService.getValue())
.toBe(stubValue, 'service returned stub value'); //利用mock依賴返回的值,進行指望判斷業務邏輯
});
複製代碼
WelcomeComponent 依賴於 UserService異步
export class WelcomeComponent implements OnInit {
welcome: string;
constructor(private userService: UserService) { }
ngOnInit(): void {
this.welcome = this.userService.isLoggedIn ?
'Welcome, ' + this.userService.user.name : 'Please log in.';
}
}
複製代碼
測試代碼async
class MockUserService {
isLoggedIn = true;
user = { name: 'Test User'};
};
複製代碼
beforeEach(() => {
TestBed.configureTestingModule({
// provide the component-under-test and dependent service
providers: [
WelcomeComponent,
{ provide: UserService, useClass: MockUserService }
]
});
// inject both the component and the dependent service.
comp = TestBed.get(WelcomeComponent);
userService = TestBed.get(UserService);
});
複製代碼
it('should not have welcome message after construction', () => {
expect(comp.welcome).toBeUndefined();
});
it('should welcome logged in user after Angular calls ngOnInit', () => {
comp.ngOnInit();
expect(comp.welcome).toContain(userService.user.name);
});
it('should ask user to log in if not logged in after ngOnInit', () => {
userService.isLoggedIn = false;
comp.ngOnInit();
expect(comp.welcome).not.toContain(userService.user.name);
expect(comp.welcome).toContain('log in');
});
複製代碼
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { BannerComponent } from './banner.component';
describe('BannerComponent', () => {
let component: BannerComponent;
let fixture: ComponentFixture<BannerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ BannerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(BannerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeDefined();
});
});
複製代碼
it('should contain "banner works!"', () => {
const bannerElement: HTMLElement = fixture.nativeElement;
expect(bannerElement.textContent).toContain('banner works!');
});
it('should have <p> with "banner works!"', () => {
const bannerElement: HTMLElement = fixture.nativeElement;
const p = bannerElement.querySelector('p');
expect(p.textContent).toEqual('banner works!');
});
//若是querySelector不能使用,
it('should find the <p> with fixture.debugElement.query(By.css)', () => {
const bannerDe: DebugElement = fixture.debugElement;
const paragraphDe = bannerDe.query(By.css('p'));
const p: HTMLElement = paragraphDe.nativeElement;
expect(p.textContent).toEqual('banner works!');
});
複製代碼
//頁面元素動態修改,測試
it('should display a different test title', () => {
component.title = 'Test Title';
fixture.detectChanges(); //顯示的進行修改檢測
expect(h1.textContent).toContain('Test Title');
});
//除去顯示聲明detectChanges,自動檢測
TestBed.configureTestingModule({
declarations: [ BannerComponent ],
providers: [
{ provide: ComponentFixtureAutoDetect, useValue: true }
]
});
複製代碼
it('should get Date diff correctly in fakeAsync', fakeAsync(() => {
const start = Date.now();
tick(100);
const end = Date.now();
expect(end - start).toBe(100);
}));
複製代碼
it('should show quote after getQuote (async)', async(() => {
fixture.detectChanges(); // ngOnInit()
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
fixture.whenStable().then(() => { // wait for async getQuote
fixture.detectChanges(); // update view with quote
expect(quoteEl.textContent).toBe(testQuote);
expect(errorMessage()).toBeNull('should not show error');
});
}));
複製代碼
it('should show quote after getQuote (spy done)', (done: DoneFn) => {
fixture.detectChanges();
// the spy's most recent call returns the observable with the test quote getQuoteSpy.calls.mostRecent().returnValue.subscribe(() => { fixture.detectChanges(); // update view with quote expect(quoteEl.textContent).toBe(testQuote); expect(errorMessage()).toBeNull('should not show error'); done(); }); }); 複製代碼
TypeError: ctor is not a constructor
複製代碼
問題緣由:provide中錯誤的配置ide
//錯誤的
providers: [{provide: OrderService, useClass: new OrderServiceMock()}]
複製代碼
//正確的
providers: [{provide: OrderService, useValue: new OrderServiceMock()}]
複製代碼
import { Injectable } from '@angular/core';
function _window() : any {
// return the global native browser window object
return window;
}
@Injectable()
export class WindowRef {
get nativeWindow() : any {
return _window();
}
}
複製代碼
import { WindowRef } from './WindowRef';
@NgModule({
providers: [ WindowRef ]
})
export class AppModule{}
複製代碼
import { WindowRef } from './WindowRef';
@Component({...})
class MyComponent {
constructor(private winRef: WindowRef) {
// getting the native window obj
console.log('Native window obj', winRef.nativeWindow);
}
}
複製代碼
本文做者:前端首席體驗師(CheongHu)測試
聯繫郵箱:simple2012hcz@126.com