Как выполнить модульное тестирование Promise catch с помощью Jasmine

У меня есть очень простая функция load(), которую я пытаюсь протестировать с помощью Jasmine. this.service.loadObject() возвращает обещание.

Как я могу проверить, что this.logService.error будет вызываться, если обещание отклонено?

load() {
    this.service.loadObject().then(x => {
       this.variable = x;
    }).catch(ex => this.logService.error(ex));
}

person Luke    schedule 17.11.2018    source источник
comment
Вероятно, в этом случае вы можете использовать Spy, чтобы узнать, действительно ли была вызвана функция.   -  person Wrokar    schedule 17.11.2018


Ответы (1)


Что-то вроде этого должно работать:

it("should catch the error", done => {
    spyOn(service, "loadObject").and.returnValue(Promise.reject("test error"));
    spyOn(logService, "error"); // Might need to mock this method too

    load();

    setTimeout(() => {
        expect(logService.error).toHaveBeenCalledWith("test error");
        done();
    });
});

Я делаю setTimeout здесь, потому что обещание отклоняется асинхронно. Но у Angular есть более чистые способы сделать это, если вам нужно.

Изменить: я не проверял это, но, судя по приведенным ниже ссылкам, использование fakeAsync в сочетании с tick или flushMicroTasks должно работать:

https://www.joshmorony.com/testing-asynchronous-code-with-fakeasync-in-angular/ https://alligator.io/angular/testing-async-fakeasync/

it("should catch the error", fakeAsync(() => {
    spyOn(service, "loadObject").and.returnValue(Promise.reject("test error"));
    spyOn(logService, "error"); // Might need to mock this method too

    load();

    // One of these
    // flushMicroTasks();
    // tick();

    expect(logService.error).toHaveBeenCalledWith("test error");
}));
person Frank Modica    schedule 17.11.2018
comment
Я не мог понять, почему это работает, пока не вспомнил, что существует только один асинхронный поток (цикл событий). Спасибо. Каковы более чистые способы сделать это? - person Luke; 17.11.2018