Как делать Unit тест юнита где идёт взаимодействие с внешним сервисом?

Добрый день.
Как сделать Unit тест юнита где идёт взаимодействие с внешним сервисом?
Используется NodeJS
Пример кода:
async SynchShopProds (task) {
        return new Promise((resolve) => {
            try {
                fetch('example.url, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json; charset=UTF-8',
                        'Authorization': `Bearer ${task.accessToken}`,
                        'User-Agent': UserAgent
                    },
                    body: JSON.stringify({ "searchTerm":null, "offerStatus":null, "categoryCode":null, "cityId":null, "start":task.start, "count":100 }),
                })
                    .then(res => res.json())
                    .then(json => {
                        console.log(json)
                        const r = json
                        if (r.errors) {
                            if (r.errors[0].type === 'InvalidTokenError') {
                                resolve({
                                    status: false,
                                    errorType: 'InvalidTokenError'
                                })
                            }
                            return
                        }
                        if (r.totalCount) {
                            if (r.offers != null) {
                                let insertProducts = ''
                                let countPlus = 0
                                r.offers.forEach(function callback(value, index, array) {
                                    let name = value.masterProduct.name.replace(/\'/g, "''")
                                    insertProducts += `INSERT INTO products ("kaspiSku", "kaspiLink", "name", "thumbnailUrl") VALUES ('${value.masterProduct.sku}', '${value.masterProduct.productUrl}', '${name}', '${value.masterProduct.primaryImage.small}') ON CONFLICT ("kaspiSku") DO NOTHING;`
                                    countPlus++
                                })
                                console.log('COUNT PLUS', countPlus)
                                poolDB.connect((err, client, done) => {
                                    const shouldAbort = err => {
                                        if (err) {
                                            console.error('Error in transaction', err.stack)
                                            client.query('ROLLBACK', err => {
                                                if (err) {
                                                    console.error('Error rolling back client', err.stack)
                                                }
                                                done()
                                            })
                                            resolve({
                                                status: false,
                                                errorType: 'DatabaseError'
                                            })
                                        }
                                        return !!err
                                    }
                                    client.query('BEGIN', err => {
                                        if (shouldAbort(err)) return
                                        client.query(insertProducts, (err, result) => {
                                            if (shouldAbort(err)) return
                                            client.query('UPDATE "synchProductsTasks" SET "totalCount" = $1, start = start + $2 WHERE "shopId" = $3', [r.totalCount, countPlus, task.shopId], (err, result) => {
                                                if (shouldAbort(err)) return
                                                client.query('COMMIT', err => {
                                                    done()
                                                    if (err) {
                                                        console.error('Error committing transaction', err.stack)
                                                        resolve({
                                                            status: false,
                                                            errorType: 'DatabaseError'
                                                        })
                                                    } else {
                                                        resolve({
                                                            status: true,
                                                            stage: 'next',
                                                            errorType: null
                                                        })
                                                    }
                                                })
                                            })
                                        })
                                    })
                                })
                                return
                            } else {
                                resolve({
                                    status: true,
                                    stage: 'finish',
                                    errorType: null
                                })
                            }
                            resolve({
                                status: true,
                            })
                        }
                    })
                    .catch(err => {
                        resolve({
                            status: false,
                            errorType: 'RequestError'
                        })
                    })
            } catch (err) {
                console.error(2, err)
                resolve({
                    status: false,
                    errorType: 'ServerError'
                })
            }
        })
    }
  • Вопрос задан
  • 45 просмотров
Решения вопроса 2
Нужно отрефакторить этот модуль так, чтобы он не делал запрос во внешний сервис напрямую.
Тогда можно будет ему, в рамках теста, подсунуть заглушку, вместо реального клиента.
Ответ написан
@d-sem
Согласно документации внешнего сервиса построить ожидаемые ответы. Например, если есть OpenAPI | Swagger, то достаточно просто подменять ответы по разным путям.

А в месте где происходит отправка запросов добавить параметр - отправлять реальный запрос или получить локально сохранённый ответ или вообще генерировать эти ответы на основании документации.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы