Почему один из этих тестов с выполнением / ожиданием работает, а другой - нет? - PullRequest
0 голосов
/ 09 октября 2018

У меня есть этот асинхронный метод, который я хочу протестировать:

async getGeneralStats(): Promise<GeneralStats> {
    console.log("getGeneralStats()");

    let recoveredGeneralStats = await this.storage.get(StorageKeyItems.GeneralStats);
    console.log("recoveredGeneralStats", recoveredGeneralStats);

    if (!recoveredGeneralStats) {
        console.warn("There were no general stats, creating new one")
        this.generalStats = new GeneralStats();
        await this.storage.set(StorageKeyItems.GeneralStats, this.generalStats);
    } else {
        this.generalStats = recoveredGeneralStats;
        console.log("Recovered GeneralStats : ");
        console.dir(this.generalStats)
    }

    console.log("Returning from getGeneralStats")
    return this.generalStats;
}

Я хочу проверить вещи (перебирать): 1. Если вызывается storage.get и вызывается storage.setкогда storage.get возвращает ноль.

Первый тест работает и работает следующим образом:

    it("should GET the GeneralStats from Storage Service ", ((done) => {
        // Arrange
        let spy = spyOn(storage, 'get').and.callFake((storageKey) => {
            done();
            return Promise.resolve(null);
        })

        // Act
        statisticsProvider.getGeneralStats();

        // Assert
        expect(spy).toHaveBeenCalledWith(StorageKeyItems.GeneralStats);
    }));

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

    it("should SET GeneralStats in Storage if not General Stats were retrieved ", ((done) => {
        // Arrange
        spyOn(storage, 'get').and.callFake((storageKey) => {
            console.log("spyGet was called");
            return Promise.resolve(null);
        })

        let spySet = spyOn(storage, 'set').and.callFake((storageKey, value) => {
            console.log("spySet was called");
                          done();
            return Promise.resolve(null);
        })

        // Act
        statisticsProvider.getGeneralStats();

        // Assert
            expect(spySet).toHaveBeenCalledWith(StorageKeyItems.GeneralStats,statisticsProvider.generalStats);

    }));

Ошибка сбоя говорит: "Expected spy set to have been called with [ 'GeneralStats', undefined ] but it was never called.", но в журнале консоли говорится другое:

getGeneralStats()
spyGet was called
recoveredGeneralStats null
There were no general stats, creating new one
spySet was called
FAILED StatisticsProvider #getGeneralStats should SET GeneralStats in Storage if not General Stats were retrieved 
Returning from getGeneralStats
ERROR Expected spy set to have been called with [ 'GeneralStats', undefined ] but it was never called. 

Я понятия не имею, почему он говорит, что он не был вызван, когда был.Я даже пытался «обмануть» и сделать переменную, которая изменится на true, когда вызывается spySet, но он все равно не работает.

    it("should SET GeneralStats in Storage if not General Stats were retrieved ", ((done) => {
        let spyWasCalled = false;
        // Arrange
        spyOn(storage, 'get').and.callFake((storageKey) => {
            console.log("spyGet was called");
            return Promise.resolve(null);
        })


        let spySet = spyOn(storage, 'set').and.callFake((storageKey, value) => {
            console.log("spySet was called");
            spyWasCalled = true;
            return Promise.resolve(null);
        })

        // Act
        statisticsProvider.getGeneralStats().then(() => {
            done();

        });

        // Assert
        expect(spyWasCalled).toBeTruthy();
    }));

Если после ввода expect() в .thenНазовите мой метод прошлым тестом, но почему он мне раньше не нужен?

    it("should SET GeneralStats in Storage if not General Stats were retrieved ", ((done) => {
        // Arrange
        spyOn(storage, 'get').and.callFake((storageKey) => {
            console.log("spyGet was called");
            return Promise.resolve(null);
        })

        let spySet = spyOn(storage, 'set').and.callFake((storageKey, value) => {
            console.log("spySet was called");

            return Promise.resolve(null);
        })

        // Act
        statisticsProvider.getGeneralStats().then(() => {

            // Assert
            expect(spySet).toHaveBeenCalledWith(StorageKeyItems.GeneralStats, statisticsProvider.generalStats);
            done();
        });

    }));

1 Ответ

0 голосов
/ 09 октября 2018

Оба теста дают противоречивые результаты.Потому что:

  1. expect() может быть выполнено до того, как целевая функция выполнила свою команду из-за выполненных асинхронных работ.- При выполнении тестовых примеров getGeneralStats() дает Promise, а может или не может перейти к выполнению expect(), что может привести к сбою.

  2. done() не в том месте.Цель done() - вызываться после завершения асинхронного теста.Поэтому вы должны вызывать его после expect() и , когда вы уверены, что все асинхронные выполнения завершены.- в первом (и втором) тестовом случае он может вообще не запускать expect()!Поскольку done() может вызываться до expect() внутри этих callFakes.

Для проверки добавьте еще console.log() до expect() (или после тоже).Таким образом, вы можете увидеть, выполняется ли замыкание callFake до или после ожидаемого значения.

Что я предлагаю

Поскольку тестируемая функция работает асинхронно, вы должны ожидатьрезультат в асинхронной манере тоже.

Жасмин задокументировала здесь .

Вы можете использовать async/await, Promise или done().Вот пример использования async/await:

it("should SET GeneralStats in Storage if not General Stats were retrieved ", (async () => {
    // Arrange
    spyOn(storage, 'get').and.callFake((storageKey) => {
        console.log("spyGet was called");
        return Promise.resolve(null);
    })

    let spySet = spyOn(storage, 'set').and.callFake((storageKey, value) => {
        console.log("spySet was called");
        return Promise.resolve(null);
    })

    // Act
    await statisticsProvider.getGeneralStats();

    // Assert
    expect(spySet).toHaveBeenCalledWith(StorageKeyItems.GeneralStats, statisticsProvider.generalStats);

}));
...