【问题标题】:Trying to test a Node.js Server process using Mocha尝试使用 Mocha 测试 Node.js 服务器进程
【发布时间】:2012-08-19 23:04:42
【问题描述】:

Node.js 的新手

制作了一个运行服务器进程并提供文件的应用程序(不使用 express 或任何框架),现在我正在尝试对其进行单元测试。

我正在尝试为此使用 mocha 测试...我打算启动我的服务器进程,然后针对它运行请求以测试预期结果(统计代码、正文内容等)

但是它不能正常工作,所有请求都无法连接到服务器......我很确定问题是因为节点正在运行一个进程循环,而服务器没有在“后台”运行在发出请求时,查询正在运行,或者服务器可能尚未运行(已启动 ASYNC)?

无论如何,我想知道测试这个的正确方法是什么,我假设我需要让服务器在后台运行(如分叉进程)和/或者我需要找到一种方法来等待服务器进程首先“启动”,但不确定如何。

或至少建议测试此类服务器进程(使用 Mocha 或其他)。

谢谢。

这是示例测试代码(自原始问题以来已更新)

var server = new Server302('./fixture/');

var instance;

describe('Tests', function() {

before(function(done) {
     instance = http.createServer(function(request, response) {
        console.log(request.url);
        server.serve(request, response);
    }).listen(8000);
    instance.on("listening", function() {
        console.log("started");
        done();
    });
});

after(function(done){
  instance.close();
  console.log("stopped");
  done();
});

it("Should fetch test.html", function(done) {
    console.log("test1");
    http.get("http://localhost:8000/", function(res) {
        res.on('data', function(body) {
            console.log(body)
            expect(body).toEqual("test");
            done();
        });
    })
});

它似乎按顺序执行,但仍然因连接错误而失败,而在使用浏览器手动测试时它可以工作:

started
test1
․․․stopped


  ✖ 1 of 1 tests failed:

  1) Tests Should fetch test.html:
  Error: connect ECONNREFUSED
  at errnoException (net.js:670:11)
  at Object.afterConnect [as oncomplete] (net.js:661:19)

【问题讨论】:

  • 测试结果仅供参考:开始 test1 ․․․stopped ✖ 3 个测试中的 3 个失败:1) 测试应获取 test.html:错误:在 errnoException (net.js:670:11) 处连接 ECONNREFUSED在 Object.afterConnect [as oncomplete] (net.js:661:19) 2) 测试应该获取 test.txt:错误:在 Object.afterConnect [as oncomplete] 处的 errnoException (net.js:670:11) 处连接 ECONNREFUSED ( net.js:661:19) 3) 测试应该得到 404:错误:在 Object.afterConnect 的 errnoException (net.js:670:11) 处连接 ECONNREFUSED [as oncomplete] (net.js:661:19)

标签: node.js automated-tests mocha.js


【解决方案1】:

在您的before 中,不要调用done,直到您收到服务器触发的“监听”事件。

before(function(done) {
    instance = http.createServer(function(request, response) {
        console.log(request.url);
        server.serve(request, response);
    }).listen(8000);
    instance.on("listening", function() {
        console.log("started");
        done();
    });
});

这应该确保您的测试连接在服务器准备好之前不会启动。

另请参阅documentation for server.listen

【讨论】:

  • 谢谢,我错过了文档中的“聆听”位。这有帮助。还有我的 http.request 缺少实际发送它们的 end() 调用-doh!
  • 简化您的生活并使用高级抽象模块来测试 HTTP。看看答案中描述的 SuperTest:stackoverflow.com/a/29968691/1480391
【解决方案2】:

还必须处理成块出现的身体,这是最后的工作,以防对其他人有帮助:

var Server302 = require('../lib/server302.js'),
http = require('http'),
assert = require("assert");

var server = new Server302('./fixture/');

var instance;

describe('Tests', function() {

before(function(done) {
    instance = http.createServer(function(request, response) {
        server.serve(request, response);
    }).listen(8100);
    instance.on("listening", function() {
        done();
    });
});

after(function(done) {
    instance.close();
    done();
});

it("Should fetch test.html", function(done) {
    console.log("test1");
    var body = "";
    http.get({host: "localhost", port:8100, path: "/"}, function(res) {
        res.on('data', function(chunk) {
            // Note: it might be chunked, so need to read the whole thing.
            body += chunk;
        });
        res.on('end', function() {
            assert.ok(body.toString().indexOf("<a href='/dummy.txt'>") !== -1);
            assert.equal(res.statusCode, 200);
            done();
        });
    })
});

it("Should fetch dummy.txt", function(done) {
    http.get({host: "localhost", port:8100, path: "/dummy.txt"}, function(res) {
        res.on('data', function(body) {
            assert.equal(res.statusCode, 200);
            assert.ok(body.toString().indexOf("test") === 0);
            done();
        });
    });
});

it("Should get 404", function(done) {
    http.get({host: "localhost", port:8100, path: "/qwerty"}, function(res) {
        assert.equal(res.statusCode, 404);
        done();
    });
});

});

【讨论】:

    【解决方案3】:

    使用 SuperTest

    这是一个使用SuperTestMocha完整而直接的示例

    var server = new Server302('./fixture/');
    var request = require('supertest');
    
    describe('Tests', function() {
      it('Should fetch test.html', function(done) {
        request(server)
          .get('/')
          .expect('test', done);
      });
    });
    

    SuperTest 允许您:

    • 使用SuperAgent 请求您的服务器(比低级别的http agent 更容易使用)。
    • 将您的服务器绑定到一个临时端口,因此无需跟踪端口(如果需要,您仍然可以手动进行)。
    • 使用与Mocha(或任何其他测试框架)配合使用的sugary expect methods

    【讨论】:

    • 我认为这行不通,因为server 不是http.Server,而是一个自定义类。您能否包含 instance 的夹具代码以显示它如何与 SuperTest 一起使用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    相关资源
    最近更新 更多