Я пытаюсь смоделировать функцию, чтобы пройти тесты, используя sinon
и mocha
.
приложение.js:
const express = require('express');
const { isValid } = require('./utils/index');
const config = require('./config.json')[process.env.NODE_ENV || 'development']
const app = express();
app.get('/', (req, res)=> {
const url = config.url;
try {
const validUrl = isValid(url)
.then(() => {
return res.redirect(`https://${url}`);
})
.catch(() => {
return res.status(400).send('Unable to redirect to the given url');
})
} catch(error) {
return res.send('Internal Server Error')
}
})
const port = process.env.port || 3000;
const server = app.listen(port, ()=> {
console.info('server listens on 127.0.0.1:3000');
})
module.exports = {server, app};
конфиг.json:
{
"development": {
"url": "www.stackoverflow.com"
},
"test": {
"url": "www.stackoverflow.com"
}
}
утилиты/index.js:
const http = require('http');
module.exports.isValid = (url) => {
const options = {
method: 'HEAD',
host: url
}
const promise = new Promise((resolve, reject) => {
const req = http.request(options, () => {
return resolve(true)
})
req.on('error', () => {
return reject(new Error('Not valid'))
})
req.end();
})
return promise;
}
тест/index.js:
const request = require('supertest');
const chai = require('chai');
const sinon = require('sinon');
const index = require('../utils/index')
const { expect } = chai;
const { server } = require('../app');
const {url} = require('../config.json')['test'];
describe('isValid Test', () => {
it('Should redirects an error when the url is not valid', async() => {
const stub = sinon.stub(index, 'isValid');
stub.withArgs(url).returns(Promise.reject(new Error('Not Valid')));
const { status } = await request(server).get('/');
expect(status).to.equal(400);
})
})
Когда я выполняю тест, я получаю эту ошибку:
(node:23622) UnhandledPromiseRejectionWarning: Error: Not Valid
at Context.it (/home/hs/perso/mockTests/chaiMock/test/index.js:17:52)
at callFn (/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runnable.js:387:21)
at Test.Runnable.run (/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runnable.js:379:7)
at Runner.runTest (/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runner.js:535:10)
at /home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runner.js:653:12
at next (/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runner.js:447:14)
at /home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runner.js:457:7
at next (/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runner.js:362:14)
at Immediate.<anonymous> (/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runner.js:425:5)
at runCallback (timers.js:705:18)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)
(node:23622) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:23622) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
url: www.stackoverflow.com
1) Should redirects an error when the url is not valid
0 passing (122ms)
1 failing
1) isValid Test
Should redirects an error when the url is not valid:
AssertionError: expected 302 to equal 400
+ expected - actual
-302
+400
at Context.it (test/index.js:22:27)
at process._tickCallback (internal/process/next_tick.js:68:7)
Попробуйте проверить значение, которое вы отправляете на «хост» по вашему запросу, я полагаю, что вы нажимаете на «www.stackoverflow.com» и получаете http-код 400, поэтому вы получаете ошибку в своем тесте
Да, но вы Конечно параметр URL-адреса, который вы получаете в isValid (url), не является www.stackoverflow.com? Потому что вы не можете получить httpCode 400, если вы отправляете неверный URL-адрес
URL-адрес был www.stackoverflow.com
, в process.env.development = developement
API будет перенаправлять на страницу stackoverflow. Если только process.env.NODE_ENV= test
заглушка не должна издеваться над ответом isValid
. В моем тесте я хочу вернуть ошибку, тогда код состояния должен быть 400. В моем случае заглушка не вызывается. Она выполняется, но не вызывается при вызове request(app).get('/')
.
Я понимаю, о чем вы говорите, но в файле config.json у вас один и тот же URL-адрес, настроенный как для разработки, так и для тестирования.
Проблема здесь в том, что ваш модуль приложения требуется и, в свою очередь, извлекает файл utils/index до того, как sinon заглушит интересующую вас функцию, я полагаю, что загрузчик модуля затем кэширует его, поэтому попытка sinon заглушить его не имеет никакого эффекта.
Чтобы убедиться, что ваш тест успешно пройден, вам нужно заглушить функцию isValid, прежде чем вам потребуется ваше приложение, т.е.
const request = require('supertest');
const chai = require('chai');
const sinon = require('sinon');
const { expect } = chai;
const index = require('../utils/index');
/* Stub here before the server is required */
const stub = sinon.stub(index, 'isValid');
const { server } = require('../app');
const { url } = require('../config.json')['test'];
describe('isValid Test', () => {
it('Should redirects an error when the url is not valid', async () => {
stub.withArgs(url).rejects('Not Valid');
const { status } = await request(server).get('/');
expect(status).to.equal(400);
});
});
Кроме того, чтобы перестать видеть отклонение необработанного обещания при выполнении тестов, вы можете использовать .rejects()
функция вместо создания собственного отклоненного обещания.
Обычно, если URL-адрес действителен (в моем случае
www.stackoverflow.com
), API перенаправляет на страницу stackoverflow. В противном случае он возвращает ошибку. В моем тесте я хочу смоделировать результат, возвращаемыйisValid
в соответствии с заданным URL.