Я хочу сделать модульный тест, чтобы проверить правильность бизнес-логи 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 }