Как проверить сервис Angular с зависимостями? - PullRequest
0 голосов
/ 13 января 2020

Я хочу выполнить модульное тестирование моего сервиса, который зависит от другого сервиса.

my.service.ts:

@Injectable({
  providedIn: 'root',
})
export class MyService {
  readonly initialObjects = [
    { title: 'Title1', url: '/title1' },
    { title: 'Title2', url: '/title2' },
    { title: 'Title3', url: '/title3' },
  ];

  objects$ = new BehaviorSubject(null);

  constructor(private anotherService: AnotherService) {
    this.updateObjects();
  }

  updateObjects() {
    this.anotherService.getAllObjects().subscribe(objects => {
      if (objects.length === 0) {
        this.objects$.next(this.initialObjects);
      } else {
        const newObjects = [];
        objects.forEach(object => {
          newObjects.push({ title: object.name, url: `some-fancy-url/${object.id}` });
        });
        this.objects$.next([...this.initialObjects, ...objects]);
      }
    });
  }
}

my.service.spe c .ts

import { TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { AnotherService } from '../another.service';
import { MyService } from './my.service';

describe('MyService', () => {
  let service: MyService;
  let mockAnotherService;

  const mockObjects = [
    { id: '70c3d78c-90d9-44f6-aadc-ba2b993ba741', title: 'title1' },
    { id: 'fa08a156-edf6-4a42-bdae-99d91b5c6f32', title: 'title2' },
    { id: '551849d8-9b36-45d6-b6de-154f700abbcc', title: 'title3' },
  ];

  beforeEach(() => {
    mockAnotherService = jasmine.createSpyObj(['getAllObjects']);

    TestBed.configureTestingModule({
      providers: [
        MyService,
        { provide: AnotherService, useValue: mockAnotherService }
      ],
    });

    service = TestBed.get(MyService);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  describe('objects observable', () => {
    it('should contain only initial objects', () => {
      mockAnotherService.getAllObjects.and.returnValue(of([]));

      expect(service.objects$.value.length).toBe(3);
    });

    it('should contain all initial objects and all other available objects', () => {
      mockAnotherService.getAllObjects.and.returnValue(of(mockObjects));

      expect(service.objects$.value.length).toBe(6);

      for (let index = 3; index < service.objects$.value.length; index++) {
          expect(service.objects$.value[index].title).toEqual(mockObjects[index].title);
      }
    });
  });
});

another.service.ts (сокращенно)

[...]

  private objects = [];

  getAllObjects() {
    return of(this.objects);
  }

[...]

Сообщение об ошибке, которое я получаю для всех тестов:

...
Ошибка типа: не удается прочитать свойство 'подписка' из неопределенного
в Jasmine
в MyService.updateObjects (http://localhost: 9877 / _karma_webpack_ / main. js: 3667: 55 )
...

Я думал, что создал шпиона с jasmine.createSpyObj, который будет предоставлен через фабрику. Я что-то здесь упустил?

1 Ответ

0 голосов
/ 13 января 2020

Поскольку вы вызываете сервис в конструкторе, любой тестовый пример будет слишком поздно для насмешки над сервисом. Вместо этого вы можете сделать следующее

  const mockObjects = [
    { id: '70c3d78c-90d9-44f6-aadc-ba2b993ba741', title: 'title1' },
    { id: 'fa08a156-edf6-4a42-bdae-99d91b5c6f32', title: 'title2' },
    { id: '551849d8-9b36-45d6-b6de-154f700abbcc', title: 'title3' },
  ];

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        MyService,
        { 
          provide: AnotherService, 
          useValue: { // you can create your fake service right here
            getAllObjects: () => of(mockObjects)
          }
        }
      ],
    });
    service = TestBed.get(MyService);
  });
...