Promise Never Resolves с помощью Axios

Я использую WDIO и определяю репортера клиентов для интеграции с api testrails. План состоял в том, чтобы использовать axios для выполнения этих запросов внутри хуков тестирования.

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

Также ни в одной из моих попыток запросы не были получены тестовыми рейками (я также протестировал несколько других URL-адресов, я почти уверен, что проблема не в месте назначения).

Я убедился, что доступ к сети и безопасность не являются факторами. Мы также пытались использовать как методы axios post, так и методы axios(), но безуспешно.

Я скопирую файл ниже, я добавил примерно дюжину попыток / конфигураций с примечаниями по каждой из них, что мы получаем. Суть проблемы заключается в методе addRun().

В большинстве случаев кажется, что мы никогда не выполняем обещание. есть одно исключение, когда мы вообще не взаимодействуем с ответом, просто регистрируемся внутри оператора then(). Если мы это сделаем, мы сможем увидеть эти журналы, но результаты вызова axios никогда не вступят в силу (запуск не создается в тестовых рельсах).

      const WDIOReporter = require('@wdio/reporter').default
const axios = require('axios').default;

module.exports = class TestrailsReporter extends WDIOReporter{
    constructor(options) {
        /*
         * make reporter to write to the output stream by default
         */
        options = Object.assign(options, { stdout: true })
        super(options)
    }

    // I have tried marking this as both async and not, no difference
    async onRunnerEnd(suite) {
        console.log("CHECKPOINT RUNNER END")
        this.recordResults(caseIds[5], results[5], 'renters api tests', 5);
    }
    /**
     * takes the results from a test suite and records them in testrails
     * @param suiteId -- the suite defined in the testrails project
     * @param projectId -- the project id defined in the testrails project
     * @param caseIds -- a list of cases with which to create the test run
     * @param results -- a list of case:result pairings
    */
    async recordResults(caseIds, results, name, projectId) {
        console.log(`CHECKPOINT RECORDING RESULTS ${projectId}`)
        let testRun = await this.addRun(results['suiteId'], caseIds['cases'], name, projectId);
        testRun.then(console.log)
        await this.addResults(testRun, results['cases']);
    }

    async addRun(suiteId, caseIds, name = '', projectId) {
        console.log("CHECKPOINT ADD RUN")
        let addRunConfig = {
            method: 'post',
            url: `https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`,
            headers: {
                'Content-Type': 'application/json',
                Authorization: token,
                Cookie: 'tr_session=041c4349-688f-440a-95a3-afc29d39320a'
            },
            data: JSON.stringify({
                suite_id: suiteId,
                include_all: false,
                case_ids: caseIds,
                name: name
            })
        };

        // let x = axios.get('https://www.google.com/')
        // console.log(x)

        axios.defaults.timeout = 1000;

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, RETURNS PENDING PROMISE TO RESPONSE
        // let response = axios(addRunConfig)
        //     .then(function (response) {
        //         console.log("WHAAAT?")
        //         return response.data.id;
        //     })
        //     .catch(function (error) {
        //         console.log("HELP!")
        //         console.log(error);
        //     });
        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, NO LOGGING APPEARS AFTER
        let response = await axios(addRunConfig)
            .then(function (response) {
                console.log("WHAAAT?")
                return response.data.id;
            })
            .catch(function (error) {
                console.log("HELP!")
                console.log(error);
            });

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT
        // await axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(
        //         function (response){
        //             console.log('WHAAAT?')
        //             console.log(response)
        //             console.log('NO WAY?')
        //         })

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, BUT RETURNS A PENDING PROMISE TO RESPONSE
        // let response = axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(
        //         function (run){
        //             console.log('WHAAAT?')
        //             console.log(run)
        //             console.log('NO WAY?')
        //         })

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, BUT RETURNS A PENDING PROMISE TO RESPONSE
        // let response = axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(
        //         function (run){
        //             console.log('WHAAAT?')
        //         })

        // THIS DOES NOT EXECUTE THE CODE INSIDE THE THEN STATEMENT, BUT RETURNS A PENDING PROMISE TO RESPONSE
        // let response = axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(run => {
        //             console.log('WHAAAT?')
        //         })

        // THIS EXECUTES THE CONSOLE.LOG INSIDE THE THEN STATEMENT, BUT NOT AFTER
        // let response = await axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(console.log('WHAAAT?'))

        // THIS EXECUTES THE CONSOLE.LOG INSIDE THE THEN STATEMENT, AND AFTER
        // let response = axios.post(`https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`, addRunConfig)
        //     .then(console.log('WHAAAT?'))

        // EXECUTES THE CONSOLE.LOG INSIDE THE THEN STATEMENT, NOTHING FROM THE CATCH, AND NOTHING AFTER
        // const response = await axios(addRunConfig).then(console.log("HI")).catch(function (error) {
        //     console.log("HELP!")
        //     console.log(error);
        // });

        console.log("ANYTHING")
        console.log(response)
        return response
    }```

3 ответа

Выяснилось, что родительский класс WDIOReporter не очень хорошо справляется с асинхронными вызовами от axios. Решение найдено здесь:https://github.com/webdriverio/webdriverio/issues/5701

Вы пробовали вызвать метод, используя вместо того, чтобы определять все в объекте addRunConfig?

Не уверен, что это имеет значение, но стоит попробовать.

Здесь есть некоторая путаница в отношении концепций определения функций, вызова функций и асинхронных функций.

Прежде всего: если вы вызываете асинхронную функцию и не хотите, чтобы вызывающая функция возвращалась до того, как эта асинхронная функция вернется, вы хотите выполнить этот вызов.

В этом случае ваша функция чего-то ожидает и, следовательно, является асинхронной. Поэтому вы, вероятно, захотите, чтобы он ждал вашего звонка в recordResults. Если вы этого не сделаете, функция завершится преждевременно и, скорее всего, не дождется результата.

      async onRunnerEnd(suite) {
    console.log("CHECKPOINT RUNNER END")
    await this.recordResults(caseIds[5], results[5], 'renters api tests', 5);
}

Во-вторых, если вы используете и вместе, значение, возвращаемое awaitвыражение - это любая функция внутри возвращаемых значений. Таким образом, все ваши попытки, которые не имеют возвращаемого значения внутри функции, вызванной by, никогда не вернут ничего, кроме недействительного обещания. Нет причин объединять эти концепции.

В-третьих, размещение вызова функции (а не объявления или ссылки) внутри предложения then немедленно вызовет эту функцию. Т.е. .then(console.log('WHAAAT?')) просто немедленно вызывает console.log, а также регистрирует несуществующую функцию в качестве обратного вызова для (поскольку не возвращает ссылку на функцию).

Наконец, передача несвязанных функций вообще не будет работать. Делать такие вещи, как testRun.then(console.log) не будет работать, в зависимости от реализации и console.log. Либо сделай testRun.then(console.log.bind(console) или же testRun.then((x) => console.log(x)) на всякий случай.


Итак, во-первых, добавьте ожидание внутри onRunnerEnd, а затем просто используйте результат ожидания без каких-либо then или поймай в свой addRun:

      async addRun(suiteId, caseIds, name = '', projectId) {
    console.log("CHECKPOINT ADD RUN")
    let addRunConfig = {
        method: 'post',
        url: `https://REDACTED.testrail.io/index.php?/api/v2/add_run/${projectId}`,
        headers: {
            'Content-Type': 'application/json',
            Authorization: token,
            Cookie: 'tr_session=041c4349-688f-440a-95a3-afc29d39320a'
        },
        data: JSON.stringify({
            suite_id: suiteId,
            include_all: false,
            case_ids: caseIds,
            name: name
        })
    };

    // let x = axios.get('https://www.google.com/')
    // console.log(x)

    axios.defaults.timeout = 1000;

    let response = await axios(addRunConfig);
    console.log(response);
    console.log(response.data.id);
    return response.data.id;
}
Другие вопросы по тегам