Модульное тестирование с частным сервисом, введенным с использованием jasmine angular2

У меня проблема с попыткой модульного тестирования службы angular. Я хочу убедиться, что эта служба правильно вызывает другую введенную в нее службу.

Допустим, у меня есть этот ServiceToTest, который вводит ServiceInjected:

ServiceToTest .service.ts

@Injectable()
export class ServiceToTest  {
    constructor(private _si: ServiceInjected) {}
    public init() {
      this._si.configure();
    }

}

ServiceInjected.service.ts

@Injectable()
export class ServiceInjected {
    constructor() {}
    public configure() {
    /*Some actions*/
    }

}

С помощью этих сервисов я пишу свой модульный тест:

const serviceInjectedStub = {
  configure(): void {}
}


describe('ServiceToTest service Test', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [ServiceToTest ,
        { provide: ServiceInjected, useValue: serviceInjectedStub }]
    });
  });
  
  it('should be initialize the service injected', inject([ServiceToTest],
    (tService: ServiceToTest) => {
      spyOn(serviceInjectedStub, 'configure');
      tService.init();
      expect(serviceInjectedStub.configure).toHaveBeenCalled();
    }));

Я ожидал, что мой тест будет положительным, но получаю следующую ошибку:

Ожидается, что будет вызвана шпионская конфигурация.

С другой стороны, все будет нормально, если я установлю внедренную службу как общедоступную:

private _si: ServiceInjected by public si: ServiceInjected

person RjHiruma    schedule 22.12.2017    source источник
comment
См. github.com/angular/angular/issues/10788. Вы можете просто внедрить реальный сервис и шпионить за ним. Или вообще не использовать DI и использовать new ServiceToTest(stub) для тестирования службы. Или используйте useFactory, как описано в проблеме.   -  person JB Nizet    schedule 22.12.2017


Ответы (3)


Вы не следите за сервисом, привязанным к вашему TestBed. Получите услугу на своем испытательном стенде

beforeEach(() => {
  TestBed.configureTestingModule({
    providers: [ServiceToTest ,
      { provide: ServiceInjected, useValue: serviceInjectedStub }]
  });
  injectedService = TestBed.get(ServiceInjected);
});

И протестируй на нем

spyOn(injectedService, 'configure').and.returnValue(/* return same data type here */);
// ...
expect(injectedService.configure).toHaveBeenCalled();
person Community    schedule 22.12.2017
comment
Спасибо, чувак !! Праздник для меня сегодня в 17 часов! :п - person RjHiruma; 22.12.2017
comment
Нет проблем, наслаждайся ими: D - person ; 22.12.2017
comment
это важная информация, которую мне не хватало, спасибо, дружище - person amansinghgusain; 04.10.2018
comment
@amansinghgusain в качестве примечания, вы не обязаны использовать тестовый стенд для его получения, вы можете просто использовать нотацию массива в своем компоненте: injectedService = component['myService']. Работает даже с частными атрибутами - person ; 04.10.2018
comment
По какой-то причине у меня это не сработало. Я до сих пор понимаю, что служба не вызывалась и, безусловно, вызывается в ngOnInit. - person HisDivineShadow; 31.12.2018
comment
Затем предоставьте минимальный воспроизводимый пример вашей проблемы и создайте новый вопрос, так как этот ответ был проверен и работает. . - person ; 02.01.2019
comment
get устарел, теперь мы используем inject - person xinthose; 23.02.2021

Или вы можете использовать jasmine.createSpyObj и указать useValue, как показано ниже:

describe('YourComponent', () => {

  let serviceInjectedSpy: jasmine.SpyObj<ServiceInjected>;

  beforeEach(async(() => {

     // notice here
     serviceInjectedSpy = jasmine.createSpyObj('ServiceInjected', ['configure']);

     TestBed.configureTestingModule({
        declarations: [YourComponent],
        providers: [
           {provide: ServiceInjected, useValue: serviceInjectedSpy}
        ],
        imports: [
         ...
        ]
     }).compileComponents().then(() => {
        fixture = TestBed.createComponent(YourComponent);
        component = fixture.componentInstance;
     });
  });

  it('should assert my test', () => {
       serviceInjectedSpy.configure.and.returnValue(/* what you want */);
       component.init();
       expect(serviceInjectedSpy.configure).toHaveBeenCalled();
  });

});
person hzitoun    schedule 03.04.2019

Использовать этот:

spyOn (serviceInjectedStub, 'configure'). and.returnValue (config); // config - это макет

person Swoox    schedule 22.12.2017