Angular - Как выполнить модульное тестирование компонента с помощью асинхронного вызова службы

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

export class MyComponent {
    constructor() {
        myService.get().then(() => {
            console.log('hello from constructor');
        });
    }
}

А потом мой юнит тест:

///////////

it('does something', () => {
    console.log('hello from unit test');
});

///////////

К сожалению, это приводит к следующему журналу:

> hello from unit test
> hello from constructor

Как я могу убедиться, что конструктор завершает работу до запуска модульного теста?

2 ответа

Не используйте конструктор для загрузки данных, реализуйте OnInit интерфейс вместо.

import { OnInit } from '@angular/core';
export class MyComponent implements OnInit {

    constructor(private myService: MyService) {}

    ngOnInit() {
        myService.get().then(() => {
            console.log('hello from constructor');
        });
    }
}
  • См. Также угловую документацию Lifecycle Hooks.
  • Не забывайте вводить свои зависимости как myService Например, я добавил его в конструктор.

тестирование

Я рекомендую вам прочитать документацию по тестированию. Информации много, но оно того стоит. Вот код, который вы бы использовали для модульного тестирования вашего компонента.

let comp: MyComponent ;
let fixture: ComponentFixture<MyComponent>;

beforeEach(async(() => {
    TestBed.configureTestingModule({
        declarations: [MyComponent],
            providers: [
                { provide: MyService, useValue: {} }
            ]
        })
        .compileComponents(); 

    TestBed.compileComponents();
    fixture = TestBed.createComponent(MyComponent);
    comp = fixture.componentInstance;
}));


it('initializes the component', fakeAsync(() => {
    var service = TestBed.get(MyService); // get your service
    service.get = () => {
            return Promise.resolve(); // you can pass data here if the service returns something
        };

    // here you could add an expect to validate component state before the call or service completes

    comp.ngOnInit(); // call ngOnInit
    tick(); // simulate the promise being resolved

    expect(service.get.toHaveBeenCalled);
    // here you could add an expect to validate component state after the service completes
}));

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

Во-первых, вы должны рассмотреть возможность удаления вызова службы из конструктора.

Во-вторых, когда вы пишете тесты для компонента, вы обычно следите за сервисными вызовами и проверяете, что они были вызваны, вы на самом деле не делаете вызов, вы его макетируете. Посмотрите документацию для "spyOn".

И наконец, если вы хотите, чтобы что-то произошло перед вашими тестами, взгляните на 'beforeEach'. В любом случае, надеюсь, это поможет.

Другие вопросы по тегам