Node.js 如何在mocha测试套件中的服务器上使用存根函数

Node.js 如何在mocha测试套件中的服务器上使用存根函数,node.js,express,unit-testing,server,mocha.js,Node.js,Express,Unit Testing,Server,Mocha.js,在express serverapp.js上测试endpoint/allowUser2时,我正在尝试存根auth.session /--auth.js-- module.exports.session=(请求、恢复、下一步)=>{ req.user=null; next(); }; /--app.js-- const express=require('express'); const auth=require('./auth'); 常量app=express(); 应用程序使用(授权会话);

在express server
app.js
上测试endpoint
/allowUser2
时,我正在尝试存根
auth.session

/--auth.js--
module.exports.session=(请求、恢复、下一步)=>{
req.user=null;
next();
};
/--app.js--
const express=require('express');
const auth=require('./auth');
常量app=express();
应用程序使用(授权会话);
app.get('/allowUser2',(请求,res)=>{
如果(!req.user)返回res.status(401.send();
if(req.user.user==2)返回res.status(200.send();
});
app.listen(4001).on('listening',()=>{
log(`HTTP服务器侦听端口4001`);
});
module.exports=app;
如果我的测试套件中只有一个测试文件
test1.js
auth
成功地被存根

/--test1.js--
让应用程序;
const sinon=要求(“sinon”);
const auth=require('../../auth.js');
const chai=要求(“chai”);
const chaiHttp=require('chai-http');
const{expect}=chai;
柴胡;柴胡;
让代理;
描述('应允许访问',()=>{
之前(异步()=>{
//删除require.cache[require.resolve('../../app.js')];//导致错误:侦听EADDRINUSE:地址已在使用中
sinon.stub(auth,'session').callsFake((req,res,next)=>{
req.user={user:1};
next();
});
app=require('../../app.js');
agent=chai.request.agent(应用程序);
});
之后(异步()=>{
auth.session.restore();
});
它('不允许访问',异步函数(){
const response=wait agent.get('/allowUser2');
期望(响应.状态).to.be.equal(200);
});
});
但是,如果我有多个需要
app.js
的测试文件,那么我就有问题了。如果另一个测试文件(如下面的
test2.js
)中已经需要
app.js
,则当在
test1.js
中再次需要时,节点不会重新加载
app.js
。这会导致
app.js
调用旧的
auth.session
函数,而不是新的存根函数。因此,用户未经身份验证,测试失败

/--test2.js--
const chai=要求(“chai”);
const chaiHttp=require('chai-http');
const app=require('../../app.js');
const{expect}=chai;
柴胡;柴胡;
const-agent=chai.request.agent(应用程序);
描述('route/allowUser2',()=>{
它(“不允许访问”),异步函数(){
const response=wait agent.get('/allowUser2');
期望(响应.状态).to.be.equal(401);
});
});
我试图通过使用
delete require.cache[require.resolve('../../app.js')]重新加载
app.js
。这在使用普通文件重新加载文件时有效,但当文件是类似于
app.js
的服务器时,会导致错误:
error:listen-EADDRINUSE:address-ready-in-use

重新创建:

  • 下载
  • npm i
  • npm测试

  • 如何在服务器上存根函数?

    更新:建议的解决方案

    一个问题是您在app.js中使用直接方法引用的方式阻止了Sinon的工作


    另一个问题(使用中的地址)是因为每次我们想要获取对应用程序的引用时,我们都试图在同一个端口中创建一个服务器。将应用程序/服务器的创建分解为单独的步骤可以缓解这个问题。

    一个解决方案是将
    app.js
    转换为一个函数,在作为参数传入的端口号上启动服务器。然后在需要时随机更改端口。我不喜欢此选项,因为可能有某些原因需要将应用程序保留在特定端口上

    app.js

    const express=require('express');
    const auth=require('./auth');
    module.exports=(端口)=>{
    常量app=express();
    应用程序使用(授权会话);
    app.get('/allowUser2',(请求,res)=>{
    如果(!req.user)返回res.status(401.send();
    if(req.user.user==2)返回res.status(200.send();
    });
    app.listen(端口).on('listening',()=>{
    log(`HTTP服务器侦听端口${port}`);
    });
    返回应用程序;
    };
    
    需要时

    app=require('../../app.js')((Math.random()*10000.toString().slice(0,4));
    
    我没有在
    app.js
    中导出
    app
    ,而是导出一个启动服务器并返回服务器实例和应用的函数。通过导出服务器实例,我可以关闭服务器。需要该应用程序才能进入chai。确保
    const app=express()
    在此函数中,而不是在此函数之前,否则它不会重新创建

    const express=require('express');
    const auth=require('./auth');
    常数端口=4000;
    module.exports=()=>{
    常量app=express();
    应用程序使用(授权会话);
    app.get('/allowUser2',(请求,res)=>{
    如果(!req.user)返回res.status(401.send();
    if(req.user.user==2)返回res.status(200.send();
    });
    app.post('/allowUser2',(请求、回复)=>{
    如果(!req.user)返回res.status(401.send();
    if(req.user.user==2)返回res.status(200.send();
    });
    返回{
    服务器:app.listen(端口).on('listening',()=>{
    log(`HTTP服务器侦听端口${port}`);
    }),
    应用程序,
    };
    };
    
    然后在我的测试中,我可以在
    之前的
    中启动服务器,并在
    之后的中关闭服务器

    let-app;
    const sinon=要求(“sinon”);
    const auth=require('../../auth.js');
    const chai=要求(“chai”);
    const chaiHttp=require('chai-http');
    const{expect}=chai;
    柴胡;柴胡;
    让服务器;
    描述('route/allowUser2',()=>{
    之前(异步()=>{
    //删除require.cache[require.resolve('../../app.js')];//导致错误:`error:listen-EADDRINUSE:address-ready-in-use`。
    sinon.stub(auth,'session').callsFake((req,res,next)=>{
    req.user={user:2};
    next();
    });
    server=require('../../app.js')();
    agent=chai.request.agent(server.a