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

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

【问题讨论】:

    标签: node.js express routing run-middleware


    【解决方案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 团队使用SuperTestRouter 执行集成测试。据我了解,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()
        })
      });
    

    更多信息:

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

    【讨论】:

    • 如何在 POST、PUT 或 PATCH 请求中发送请求正文?
    • 好问题。通过传递选项参数。 (例如app.runMiddleware('/path',{method:'post'}, callback).
    • 是的,但是如何设置实际的请求正文?
    • 有可能。你在 GitHub 上看到模块页面了吗?有一个例子。如果你没有找到它,我会在这里回答
    • 我查看了here,但没有找到任何设置 POST 请求正文的示例。
    猜你喜欢
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 2012-10-04
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多