不带依赖的Service

Service不带有 constructor 或者 constructor 的不含参数的即为不带依赖的Service。如下方的CityService

  1. import { Injectable } from '@angular/core';
  2. import { Subject } from 'rxjs';
  3. @Injectable()
  4. export class CityService {
  5. private city: string;
  6. citySubject = new Subject<string>();
  7. getCity() {
  8. return this.city;
  9. }
  10. setCity(city: string) {
  11. this.city = city;
  12. this.citySubject.next(this.city);
  13. }
  14. getCitys() {
  15. return ['北京','上海','广州','深圳'];
  16. }
  17. getObservableValue() {
  18. return this.citySubject.asObservable();
  19. }
  20. getPromiseValue() {
  21. return this.citySubject.toPromise();
  22. }
  23. }

使用new操作符即可创建该类Service的实例,并进行测试。

  1. import { CityService } from "./city3.service"
  2. describe('CityService', () => {
  3. let service: CityService;
  4. beforeEach(() => {
  5. service = new CityService();
  6. });
  7. it('#getCities 应该返回城市列表', () => {
  8. const cities = service.getCities();
  9. expect(cities).toBeTruthy();
  10. expect(cities.length).toBeGreaterThanOrEqual(1);
  11. });
  12. it('getObservableValue 能正确返回设置值', (done) => {
  13. service.getObservableValue().subscribe(city => {
  14. expect(city).toBe('广州');
  15. done()
  16. });
  17. service.citySubject.next('广州');
  18. });
  19. it('#getPromiseValue 能正确返回设置值', done => {
  20. service.getPromiseValue().then(city => {
  21. expect(city).toBe('北京');
  22. done();
  23. });
  24. service.citySubject.next('北京');
  25. service.citySubject.complete();
  26. });
  27. });

带有依赖的Service

注入的Service依赖足够简单

  1. describe('MasterService without Angular testing support', () => {
  2. let masterService: MasterService;
  3. it('#getValue should return real value from the real service', () => {
  4. masterService = new MasterService(new ValueService());
  5. expect(masterService.getValue()).toBe('real value');
  6. });
  7. it('#getValue should return faked value from a fake object', () => {
  8. const fake = { getValue: () => 'fake value' };
  9. masterService = new MasterService(fake as ValueService);
  10. expect(masterService.getValue()).toBe('fake value');
  11. });
  12. it('#getValue should return stubbed value from a spy', () => {
  13. const valueServiceSpy =
  14. jasmine.createSpyObj('ValueService', ['getValue']);
  15. const stubValue = 'stub value';
  16. valueServiceSpy.getValue.and.returnValue(stubValue);
  17. masterService = new MasterService(valueServiceSpy);
  18. expect(masterService.getValue())
  19. .toBe(stubValue, 'service returned stub value');
  20. expect(valueServiceSpy.getValue.calls.count())
  21. .toBe(1, 'spy method was called once');
  22. expect(valueServiceSpy.getValue.calls.mostRecent().returnValue)
  23. .toBe(stubValue);
  24. });
  25. });

使用 TestBed 测试服务

TestBed 是 Angular 测试实用工具中最重要的。 TestBed 创建了一个动态构造的 Angular 测试模块,用来模拟一个 Angular 的 @NgModule 。
TestBed.configureTestingModule() 方法接受一个元数据对象,它可以拥有@NgModule的大部分属性。
要测试某个服务,你可以在元数据属性 providers 中设置一个要测试或模拟的服务数组。

  1. let masterService: MasterService;
  2. let valueServiceSpy: jasmine.SpyObj<ValueService>;
  3. beforeEach(() => {
  4. const spy = jasmine.createSpyObj('ValueService', ['getValue']);
  5. TestBed.configureTestingModule({
  6. providers: [
  7. MasterService,
  8. { provide: ValueService, useValue: spy }
  9. ]
  10. });
  11. masterService = TestBed.inject(MasterService);
  12. valueServiceSpy = TestBed.inject(ValueService) as jasmine.SpyObj<ValueService>;
  13. });

注意: TestBed.get() 已在 Angular 9 中弃用。