【问题标题】:How to Make a Call to Koa.js App Instance for Unit Tests如何调用 Koa.js 应用程序实例进行单元测试
【发布时间】:2015-10-06 12:33:42
【问题描述】:

我不知道如何称呼这可能是“对 koa 路由器的静态调用”?如果您从技术上谈论它,这似乎是我真正想要实现的目标的正确措辞吗?

无论如何,我正在使用koa-router 并且正在编写单元测试(不是集成测试)。所以我不想在我的 koa 应用程序上调用 .listen() ,因为这个原因......它会创建一个 http 服务器,现在让我的测试成为集成测试。

在我的测试中,我只是想直接调用应用程序对象实例并调用路由,并且能够不返回任何结果并检查我是否在响应中没有返回任何结果。

你怎么能做到这一点?我找不到示例,我已经尝试了各种伪代码尝试对 koa 应用程序对象。

【问题讨论】:

  • 针对应用程序本身的测试是一项集成测试。您是要测试应用本身(集成)还是单独的中间件(单元测​​试)?
  • 没有。我正在测试我的 API 的接口(合同)。我正在通过 Koa 公开 RESTful 端点。这意味着我对那些端点进行 TDD,因此我的 TDD 是非集成的。它们是单元测试,不应该在 app.Listen() 上进行测试。我只是在测试实际的代码,即 SUT,不,我不是在测试 Koa 的框架。您使用框架,但您测试域逻辑或其他任何东西。我的域逻辑包括路由。因为如果开发人员破坏了路线,他们只是破坏了 BDD 测试并破坏了业务需求。这就是我开发代码的方式。
  • 您在这里混淆了术语。如果您正在测试您的路由,即测试GET /,那么您必须将应用程序的该部分作为一个整体进行测试——这使其成为一个集成测试。如果您正在测试单个功能(您不是),那么您就是在进行单元测试。您不想测试将您的应用程序与 koa 连接的层(顺便说一句,它应该非常薄),您只想集成测试那一点。
  • “创建并返回一个 HTTP 服务器”——直接来自 koa 文档。对于 app.listen()。
  • 我没有测试所有单独的功能,TDD'ers 发现你可以过度测试这条路线。使用单元测试和集成测试来测试边界,并从边界(例如,您的单元......其中一个单元可能是服务合同)进行测试驱动,这会推动您对代码进行 TDD。时代变了,人们不再使用传统的 TDD,您为每个功能创建大量测试。测试过于耦合,最终会导致测试失败,您只需要测试边界单元和代码单元。

标签: node.js koa


【解决方案1】:

如果您想测试 koa-router 路由到的函数,那么只需对该函数执行单元测试并将路由排除在外。

对我来说,听起来您有一个 app.js 之类的文件,其中包含您的所有代码。您可以做的是创建一个 router.js 文件来放置您的路由绑定和一个 services.js 文件,您可以在其中放置您的应用程序逻辑。

所以例如 app.js 可能看起来像:

var koa = require("koa");
var app = module.exports = koa();
var router = require('./router.js');

app.use(router.unsecured.middleware());

app.listen(3000);

router.js 可能看起来像:

var router = require("koa-router");
var service = require("./services.js");

var unsecured = module.exports.unsecured = new router();

unsecured.post('/account/signin', service.signinUser);
unsecured.post('/account/register', service.registerUser);

services.js 可能看起来像:

module.exports.signinUser  = function*(signinDetails) {
  // contains your application signin logic
};

module.exports.registerUser  = function*(registerDetails) {
  // contains your application register logic
};

因此,您可以通过这种方式单独测试 services.js。我认为单独测试 router.js 没有任何价值,因为它是如此微不足道。正如@Dan Pantry 所示,您可以使用 supertest 在集成测试中测试路由。

编辑:

所以这是我正在玩的一个小实验测试,以测试路由是否正确。我使用 mocha 作为测试运行器,并使用我在原始代码中发布的代码示例。

// standard library
var assert = require("assert");

// in app objects
var router = require('./router.js');
var service = require('./service.js');

describe("routing tests", function() {

  it("test register routing, POST", function*(done) {
    // arrange
    var unsecured = router.unsecured;
    var path = '/account/register';
    var httpMethod = 'POST';
    var expected = service.register.toString();
    var actual;

    // act
    for (var i = 0; i < unsecured.stack.length; i++)
    {
      var pathMatch = unsecured.stack[i].path === path;
      var methodMatch = unsecured.stack[i].methods.indexOf(httpMethod) >= 0;

      if (pathMatch && methodMatch)
      {
        actual = unsecured.stack[i].middleware.toString();
        break;
      }
    }

    // assert
    try {
      assert.equal(expected, actual);
      done();
    } catch(err) {
      done(err);
    }
  });    
});

可能有一种更简洁的方法(以及测试多条路径的更模块化的方法),但正如我所说,这只是验证路由调用正确服务的基本示例。我正在做的是深入研究 koa-router 对象,以根据 HTTP 方法(例如 POST、GET 等)验证哪些路径绑定到哪些服务代码。

如果您在模块中包含路由和服务,则此测试完全避免处理主要的 koa 应用程序。虽然从技术上讲,这个测试跨越了多个单元(路由和服务代码),所以从技术上讲它是一个集成测试,但这确实意味着你不要靠近app.listen(),这是你不想在测试中调用的。

【讨论】:

  • 是的,这就是我已经将它隔离的方式......但是你有你的 app.listen 在 app.js 所以这是一个巨大的差异,好东西。
  • 测试路由器的原因是因为一些愚蠢的程序员可以搞定它。他们可以删除一个路由,他们可能会弄乱 js,我们最终会得到一个空路由器,各种各样的事情,所以我认为测试那个单元很重要。
  • 检查我的编辑,寻找一种可能的方法来避免你担心的事情,同时也避免超测试方法。
  • 如果没有 app.listen 它将无法工作,这将使我的测试集成测试。我不想要一个 http 服务器的实例,我想测试 koa 中间件本身并直接调用应用程序实例方法。
  • 来自 node.js 的不安全值在哪里?
猜你喜欢
  • 2014-06-03
  • 2012-01-08
  • 2016-04-04
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
  • 1970-01-01
  • 2019-01-01
  • 2012-03-21
相关资源
最近更新 更多