Javascript 使用sinon和mocha执行测试时不执行存根函数

Javascript 使用sinon和mocha执行测试时不执行存根函数,javascript,node.js,ecmascript-6,mocha.js,sinon,Javascript,Node.js,Ecmascript 6,Mocha.js,Sinon,我试图模拟一个函数,以便通过使用sinon和mocha的测试 app.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)

我试图模拟一个函数,以便通过使用
sinon
mocha
的测试

app.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.log('server listens on 127.0.0.1:3000');
})

module.exports = {server, app};
config.json:

{
"development": {
    "url": "www.stackoverflow.com"
}, 
"test": {
    "url": "www.stackoverflow.com"
}

}
utils/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;
}
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);

    })
})
test/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;
}
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)
(节点:23622)未处理的PromisejectionWarning:错误:无效
在Context.it(/home/hs/perso/mockTests/chaiMock/test/index.js:17:52)
在callFn(/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runnable.js:387:21)
在Test.Runnable.run(/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/Runnable.js:379:7)
在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
下一步(/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
下一步(/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runner.js:362:14)
马上。(/home/hs/perso/mockTests/chaiMock/node_modules/mocha/lib/runner.js:425:5)
运行回调时(timers.js:705:18)
在tryOnImmediate(timers.js:676:5)
在processImmediate(timers.js:658:5)
(节点:23622)未处理的PromisejectionWarning:未处理的承诺拒绝。此错误源于在没有catch块的异步函数中抛出,或者拒绝未使用.catch()处理的承诺。(拒绝id:1)
(节点:23622)[DEP0018]弃用警告:未处理的承诺拒绝已弃用。将来,未处理的承诺拒绝将使用非零退出代码终止Node.js进程。
网址:www.stackoverflow.com
1) 当url无效时,应重定向错误
0通过(122ms)
1失败
1) 有效测试
当url无效时,应重定向错误:
AssertionError:预期302等于400
+预期-实际
-302
+400
在Context.it(test/index.js:22:27)
在进程中。_tick回调(内部/process/next_tick.js:68:7)

试着检查您请求时在“主机”上发送的值,我相信您正在点击“www.stackoverflow.com”并获得http代码400,这就是您在测试中出错的原因

试着检查您请求时在“主机”上发送的值,我相信您正在点击“www.stackoverflow.com”获取http代码400这就是为什么您的测试出现错误的原因这里的问题是,您的应用程序模块是必需的,并且在sinon存根您感兴趣的函数之前,会拉入UTIL/索引文件,我相信模块加载程序会缓存它,因此sinon尝试存根它没有效果

要成功通过测试,您需要在需要应用程序(即

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);
  });
});

此外,要在测试运行时停止看到未处理的承诺拒绝,您可以使用,而不是创建您自己的拒绝承诺。

这里的问题是,您的应用程序模块是必需的,并且反过来在sinon存根您感兴趣的函数之前拉入UTIL/索引文件,我相信模块加载器会缓存它,所以sinon尝试存根它没有效果

要成功通过测试,您需要在需要应用程序(即

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);
  });
});

另外,要在测试运行时停止看到未处理的承诺拒绝,您可以使用,而不是创建自己的拒绝承诺。

通常,如果url有效(在我的例子中是
www.stackoverflow.com
),api将重定向到stackoverflow页面。否则,它将返回错误。在我的测试中,我想根据给定的url模拟
isValid
返回的结果。是的,但是您确定在isValid(url)中接收的url参数不是www.stackoverflow.com吗?因为如果发送的url无效,您将无法收到httpCode 400。url为
www.stackoverflow.com
,在
process.env.development=development
中,api将重定向到stackoverflow页面。除非当
process.env.NODE\u env=test
时,存根应该模拟
isValid
的响应。在我的测试中,我想返回一个错误,然后状态代码应该是400。在我的例子中,存根没有被调用。它被执行,但在调用
请求(app).get(“/”)
时没有被调用。我理解你的意思,但是在config.json文件中,如果URL有效,你为开发和测试配置了相同的URL(在我的例子中
www.stackoverflow.com
)api重定向到stackoverflow页面。否则,它将返回一个错误。在我的测试中,我想根据给定的url模拟
isValid
返回的结果。是的,但是您确定在isValid(url)中接收的url参数不是www.stackoverflow.com吗?因为如果发送的url无效,您将无法收到httpCode 400。url为
www.stackoverflow.com
,在
process.env.development=development
中,api将重定向到stackoverflow页面。除非当
process.env.NODE\u env=test
时,存根应该模拟
isValid
的响应。在我的测试中,我想返回一个错误,然后状态代码应该是400。在我的例子中,存根没有被调用。它被执行,但在调用
request(app).get('/')
时没有被调用。我理解你的意思,但是在config.json文件中,你为开发和测试配置了相同的URL