18

我是 Node.js、Mongoose 和在这个环境中测试的新手。我在单独的文件中声明了以下架构。

Issue = mongoose.model("Issue", {
  identifier: String,
    date: String,
    url: String,    
    name: String,
    thumbnailURL: String
});

然后我有这个方法,它只返回IssueMongoDB 集合中的所有实例。

function issues(request, response) {
  response.setHeader('Content-Type', 'text/json');

  Issue.find().sort('date').exec(function(error, items) {
    if (error) {
      response.send(403, {"status": "error", "error:": exception});
    }
    else {
      response.send(200, {"issues": items});
    }
  });
}

我已经通过实验走了这么远,现在我想测试它,但我遇到了一个问题。如何在不设置 MongoDB 连接等的情况下进行测试。我知道我可以设置所有这些东西,但这是一个集成测试。我想编写单元测试来测试以下内容:

  • 该函数是否正确设置了内容类型
  • 函数是否按date字段排序
  • 发生错误时函数是否返回 403?
  • ... 等等

我很想知道如何重构现有代码以使其更易于单元测试。我尝试过创建第二个调用的函数,接受responseItem模式对象作为参数,但感觉不对。有人有更好的建议吗?

4

4 回答 4

8

Mongoose model(your Issue) 返回对象的一个​​新实例Query。新query实例可以exec通过prototype. (猫鼬3.8~)

如果你想返回一个错误,你可以写:

sinon.stub(mongoose.Query.prototype, "exec").yields({ name: "MongoError" }, null);
于 2014-11-23T13:42:14.827 回答
6

在我的节点代码中使用 mocha 与 chaijs 和 sinonjs 类似这种方法对我有用:

var should = require('chai').should(),
sinon = require('sinon'),
mongoose = require('mongoose');

it('#issues() handles mongoosejs errors with 403 response code and a JSON error message', function (done) {

// mock request
var request = {};

// mock response
var response = {};
response.setHeader = function(header) {};
response.send = function (responseCode, jsonObject) {
    responseCode.should.equal(403);
    jsonObject.stats.should.equal('error');
    // add a test for "error:": exception
    done();
}

var mockFind = {
    sort: function(sortOrder) {
        return this;
    },
    exec: function (callback) {
        callback('Error');
    }
}

// stub the mongoose find() and return mock find 
mongoose.Model.find = sinon.stub().returns(mockFind);

// run function
issues(request, response);

});
于 2013-11-21T03:26:11.453 回答
1

我不确定如何测试 Content-Type,我自己也没有测试过这段代码,但如果它不起作用,我很乐意提供帮助。这对我来说似乎很有意义。基本上我们只是创建了一个回调,因此我们可以将response.send实际的自定义逻辑移出,然后我们可以通过该回调进行测试。让我知道它是否不起作用或有意义。您可以使用其他人发布的链接来防止必须连接到数据库。

Issue = mongoose.model("Issue", {
    identifier: String,
    date: String,
    url: String,    
    name: String,
    thumbnailURL: String
  });

  function issues(callback, request, response) {
    Issue.find().sort('number').exec(function(error, items) {
      if (error) {
        callback(403, {"status": "error", "error:": exception});
      }
      else {
        callback(200, {"issues": items});
      }
    });
  }

  //Note: probably don't need to make a whole new `sender` function - depends on your taste
  function sender(statusCode, obj) {
    response.setHeader('Content-Type', 'text/json');
    response.send(statusCode, obj);
  }

  //Then, when you want to implement issues
  issues(sender, request, response);

  //The tests - will depend on your style and test framework, but you get the idea
  function test() {
    //The 200 response
    issues(function(code, obj) {
      assert(code === 200);
      assert(obj.issues === ??);   //some testable value, or just do a truthy test
      //Here, you can also compare the obj.issues item to the proper date-sorted value
    });

    //The error response
    issues(function(code, obj) {
      assert(code === 403);
      assert(code.status === 'error');
    });
  }
于 2013-10-09T23:20:17.487 回答
0

一个好的起点是:

  1. 研究stubs 和 mocks的概念,并测试双打。
  2. 查看Sinon.js,它是 Node.JS 选择的 Mocking 框架
于 2013-10-09T23:00:44.677 回答