Почему Sinon не заглушает функцию на сервере Express? - PullRequest
0 голосов
/ 07 мая 2020

Я хочу сделать модульный тест, чтобы проверить правильность бизнес-логи c для добавления продукта в систему. Но в процессе добавления продукта система должна загрузить изображение продукта в Cloudinary. Зная, что модульный тест должен выполняться изолированно, я включил в AddProduct.test.js файл библиотеку Sinon, чтобы заглушить метод uploadImage() в cloudinary.js файл.

Следуя основным c шагам, чтобы заглушить методы, выполняющие HTTP запросов, а затем выполнив тест, изолирующий мой хост Inte rnet, я понял, что тест завершился неудачно со следующим выводом:

Hi, Idk why I am running in the unit test
Image upload error:
{
  "errno":"ENOTFOUND",
  "code":"ENOTFOUND",
  "syscall":"getaddrinfo",
  "hostname":"api.cloudinary.com"
}

Я интерпретирую, что реальный метод uploadImage() выполняется вместо заглушки Я запрограммировал в файле AddProduct.test.js.

В этом случае, что я мог бы попытаться определить, почему мой тест не работает?

Вложения

Структура проекта

backend
|-src
|   |-controllers
|   |   |-productController.js
|   |-models
|   |   |-cloudinary.js
|   |--server.js
|-test
|   |-resources
|   |   |-mock_outputs
|   |       |-addProduct.json
|   |-AddProduct.test.js

AddProduct.test. js

const superAgent = require('superagent')
const statusCode = require('http-status-codes')
const chai = require('chai')
const sinon = require('sinon')
const { expect } = chai

const cloudinary = require('../src/models/cloudinary')
const { correctCloudinaryResponse } = require('./resources/mock_outputs/addProduct.json')

const apiUrl = 'http://127.0.0.1:3001'
let cloudinaryStub = null

describe('AddProduct tests', () => {
    beforeEach(() => {
        cloudinaryStub = sinon.stub(cloudinary, 'uploadImage')
    })

    afterEach(() => {
        sinon.restore()
    })

    it('should add the product without errors', async () => {
        cloudinaryStub.returns(Promise.resolve(correctCloudinaryResponse))
        try {
            await superAgent.post(`${apiUrl}/product`)
                .accept('application/json')
                .field('name', 'Lego')
                .field('category', 13)
                .field('country', 'Colombia')
                .field('countrySubdivision', 'Valle del Cauca')
                .attach('picture', './test/resources/lego.jpg', { filename: 'lego.jpg', contentType: 'image/jpeg' })
                .set('Authorization', response.body.token)

            expect(response.status).to.equal(statusCode.CREATED)
        } catch (error) {
            let message = error.response.error.text ? error.response.error.text : error.response.text
            expect.fail(message)
        }
    })
})

облачный. js

const cloudinary = require('cloudinary')

cloudinary.config({
    cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
    api_key: process.env.CLOUDINARY_API_KEY,
    api_secret: process.env.CLOUDINARY_API_SECRET
})

const uploadImage = async (imagePath, folderName) => {
    console.debug('Hi, Idk why I am running in the unit test')
    let response = null
    try {
        const uploadOptions = {
            folder: folderName
        }
        response = await cloudinary.v2.uploader.upload(imagePath, uploadOptions)
        return response
    } catch (error) {
        throw new CloudinaryException(`Image upload error: ${error}`)
    }
}

class CloudinaryException extends Error {
    constructor(message) {
        super(message)
    }
}

module.exports = { uploadImage }

productController. js

const cloudinary = require('../models/cloudinary')

const addProduct = async function (req, res) {
    let clientResponse = null
    let product = null
    try {
        if (req.file !== undefined) {
            // Upload image to Cloudinary
            const imageFolder = product.USERS_USER_EMAIL.split('@')[0]
            console.debug('Calling cloudinary')
            const {url, public_id} = await cloudinary.uploadImage(req.file.destination + '/' + req.file.filename, imageFolder)
        }
        /**
         * Here goes other irrelevant stuff
         **/
        clientResponse = res.status(201).json({message: 'Product saved successfully'})
    } catch (error) {
        clientResponse = res.status(500).json({ message: 'An error ocurred adding the product', error: error})
    }
    return clientResponse
}

module.exports = { addProduct }
...