Окончательная версия Angular2: метод Injected Service при модульном тесте возвращает неопределенное значение

Я пытаюсь написать несколько модульных тестов для компонента, в который были введены некоторые службы, для загрузки данных с сервера. Данные загружаются в этот компонент методом OnInit(). Я пытаюсь, чтобы метод службы возвращал некоторые фиктивные данные, используя spyOn. Ниже приведена настройка модульного теста:

let comp: MyComponent;
let fixture: ComponentFixture<MyComponent>;
let staticDataService: any;
let spy: jasmine.Spy;
let allCountries: string[];

describe('MyComponent', () => {
beforeEach( async(() => {

    TestBed.configureTestingModule({
        imports : [ FormsModule, HttpModule ],
        declarations : [MyComponent],
        providers: [ StaticDataService ]
    })
    .compileComponents();
}));

beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    comp = fixture.componentInstance;
    staticDataService = fixture.debugElement.injector.get(StaticDataService);
    allCountries = [] = ["US", "UK"];
    spy = spyOn(staticDataService, 'getCountries').and.returnValue(Promise.resolve(allCountries));
    });
it('Countries should be set', () => {
    expect(comp.allCountries).toEqual(allCountries);
    }); 
});

Ниже приведен класс компонента, который я тестирую.

@Component({
  moduleId: module.id,
  selector: 'myeditor',
  templateUrl: 'my.component.html',
  styleUrls: ['my.component.css']
})
export class MyComponent implements OnInit {
  allCountries: string[];
  constructor(private _staticDataServices: StaticDataService) {}
  ngOnInit() {
    this.getDataFromServer();
  }

  getDataFromServer()
  {
    this.allCountries = this._staticDataServices.getCountries();
  }

Я получаю следующую ошибку -

    Chrome 53.0.2785 (Windows 7 0.0.0) MyComponent Countries should be set FAILED
    [1]     Expected undefined to equal [ 'US', 'UK' ].

При тех же модульных тестах несколько других тестов работают нормально, которые не зависят от внедряемых сервисов. Получение «неопределенного» при тестировании свойств, установленных службами. Может кто-нибудь, пожалуйста, помогите, что я делаю неправильно здесь?

Спасибо


person Raj    schedule 16.10.2016    source источник


Ответы (1)


  1. Вам нужно позвонить fixture.detectChanges(), чтобы вызвать ngOnInit.

    fixture = TestBed.createComponent(MyComponent);
    fixture.detectChanges();
    
  2. getCountries возвращает Promise, поэтому вам нужно then его, иначе значение allCountries будет просто обещанием, а не данными

    getDataFromServer() {
      this._staticDataServices.getCountries().then(data => {
        this.countries = data;
      });
    }
    
  3. Поскольку промис асинхронный, вам нужно использовать async и дождаться завершения асинхронной задачи, вызвав fixture.whenStable()

    import { async } from '@angular/core/testing';
    
    it('...', async(() => {
      fixture.whenStable().then(() => {
        expect(comp.allCountries).toEqual(allCountries);
      })
    })
    

ОБНОВИТЬ

Не видя StaticDataService, я предполагаю, что вы пытаетесь ввести в него Http. Это не будет работать в тестовой среде без дополнительной настройки. Что я предлагаю вам сделать, так это просто сделать сервис макетом

staticDataService = {
  getCountries: jasmine.createSpy('getCountries').and.returnValue(...);
}

providers: [
  { provide: StaticDataService, useValue: staticDataService }
]
person Paul Samsotha    schedule 16.10.2016
comment
Спасибо за ответ. Когда я применяю эти изменения, я получаю следующую ошибку: - person Raj; 17.10.2016
comment
Спасибо за ответ. Когда я применяю эти изменения, я получаю следующую ошибку: [1] TypeError: this._staticDataService.getCountries(...).subscribe не является функцией Не уверен, почему этот метод вызывается, когда он должен быть переопределен методом/значениями указано в spyOn. - person Raj; 17.10.2016
comment
Вы не можете вызвать subscribe по обещанию (это то, что возвращает макет). Это только для наблюдаемых. Это разные вещи. Вам нужно позвонить then по обещанию. Если вы хотите вместо этого выпустить наблюдаемое в своем макете, то and.returnValue(Observable.of(allCountries)) - person Paul Samsotha; 17.10.2016
comment
Вам нужно будет импортировать rxjs/add/observable/of - person Paul Samsotha; 17.10.2016
comment
Спасибо, это помогает. Он прошел через метод OnInit. Далее необходимо устранить некоторые ошибки синтаксического анализа html, появляющиеся в тех же тестах. - person Raj; 17.10.2016