是否可以通过“假”请求直接从代码中调用 Express Router?

Posted

技术标签:

【中文标题】是否可以通过“假”请求直接从代码中调用 Express Router?【英文标题】:Is it possible to call Express Router directly from code with a "fake" request? 【发布时间】:2016-01-10 11:04:32 【问题描述】:

与this question 相切,我想知道是否有一种方法可以在不通过 HTTP 的情况下触发 Express Router?

【问题讨论】:

【参考方案1】:

路由器有一个"private" method named handle,它接受请求、响应和回调。您可以查看 Express 对其Router 的测试。一个例子是:

it('should support .use of other routers', function(done)
    var router = new Router();
    var another = new Router();

    another.get('/bar', function(req, res)
      res.end();
    );
    router.use('/foo', another);

    router.handle( url: '/foo/bar', method: 'GET' ,  end: done );
  );

Express 团队使用SuperTest 对Router 执行集成测试。据我了解,SuperTest 仍然使用网络,但它们会为您处理所有这些,因此它的行为就像测试都在内存中一样。 SuperTest 似乎被广泛使用并且是一种可接受的测试路线的方法。

顺便说一句,您没有说您要测试什么,但如果您的目标是测试某些路由,SuperTest 的替代方法可能是将您的路由中的逻辑提取到一个单独的模块中,该模块可以独立测试快递。

改变:

routes
|
-- index.js

到:

routes
|
-- index.js
|
controllers
|
-- myCustomController.js

然后测试可以简单地以myCustomController.js 为目标并注入任何必要的依赖项。

【讨论】:

@oligofren:我已经更新了答案以显示如何向路由器发送虚假请求。 哈哈,你甚至添加了一个链接到几乎与我相同的行! 如果有人需要在控制器上使用它,您可以处理更改 URL (req.url="/whatever") 的重新路由请求并使用:req.app._router.handle (req,res,next); 你是最棒的谢谢【参考方案2】:

通过查看 Express 的源代码,我发现确实有一个 API 与我希望的一样简单。它记录在the tests for express.Router。

/** 
* @param express.Router router 
*/
function dispatchToRouter(router, url, callback) 

    var request = 
        url  : url,
        method : 'GET'
    ;

    // stub a Response object with a (relevant) subset of the needed
    // methods, such as .json(), .status(), .send(), .end(), ...
    var response = 
        json : function(results) 
            callback(results);
        
    ;

    router.handle(request, response, function(err) 
        console.log('These errors happened during processing: ', err);
    );

但是......缺点是,它最初没有被记录的原因是:它是 Router.prototype 的私有函数:

/**
 * Dispatch a req, res into the router.
 * @private
 */

proto.handle = function handle(req, res, out) 
  var self = this;
  ...

所以依赖这段代码并不是世界上最安全的事情。

【讨论】:

看起来我们找到了同样的东西。希望有一些不是私有方法的东西。 我可能正忙着添加我在您编辑您的信息时找到的信息 :-) 我将使用私有方法,因为这种方法可以简化很多。只需添加一堆测试,以防 Express 升级会破坏界面。【参考方案3】:

您完全可以使用run-middleware 模块。您通常创建一个快速应用程序,然后您可以使用您的参数调用该应用程序

it('should support .use of other routers', function(done)
    var app=require('express')()      
    app.get('/bar', function(req, res)
      res.status(200).end();
    );
    app.runMiddleware('/bar',options,function(responseCode,body,headers)
        console.log(responseCode) // Should return 200
        done()
    )
  );

更多信息:

模块页面在Github & NPM; Examples of use run-middleware module

披露:我是这个模块的维护者和第一个开发者。

【讨论】:

如何在 POST、PUT 或 PATCH 请求中发送请求正文? 好问题。通过传递选项参数。 (例如app.runMiddleware('/path',method:'post', callback). 是的,但是如何设置实际的请求正文? 有可能。你在 GitHub 上看到模块页面了吗?有一个例子。如果你没有找到它,我会在这里回答 我查看了here,但没有找到任何设置 POST 请求正文的示例。

以上是关于是否可以通过“假”请求直接从代码中调用 Express Router?的主要内容,如果未能解决你的问题,请参考以下文章

SAP打印机配置

是否有任何应用程序从Google日历活动创建(假)传入短信?

取消 xmlrpc 客户端请求?

是否可以直接从 html img 标签 src 向服务器请求文件并使用 jwt 身份验证标头加载它?

无法使用 Express.js 从请求中获取 POST 正文

Gingerbread 浏览器跨域响应连接错误