专栏首页编程之旅Nodejs中编写异步的单元测试代码

Nodejs中编写异步的单元测试代码

在Nodejs的开发过程中,异步这个话题是无论如何都躲不过去的,关于异步的文章已经有过许多篇了,我也不打算写在开发Web应用的过程中,该如何在Nodejs中处理异步代码。在前些日子,我跟单元测试覆盖率这个指标杠上了,因为自己在写一个Nodejs的工程,我希望这个工程的测试代码量不要太少,目标是100%的行覆盖率,所以最近写了许多的单元测试代码。使用的测试框架是Mocha,断言库是Chai,那么今天我们就来聊聊在单元测试中,处理异步代码的各种姿势。

处理promise

const { query } = require('../app/utils/async-db');
const { should } = require('chai');
const mysql = require('mysql');
should();

/**
 * 测试数据库连接的正确状态
 */
describe('mysql connect success state', function() {
  it('should return an array', function(done) {
    let sql = 'SELECT * FROM `Users`';
    query(sql)
      .then((rows) => {
        rows.should.be.an('array');
        done();
      })
      .catch(err => {
        done(err);
        throw err;
      });
  });
});

先来看看今天的例子,这段代码就是测试数据库连接状态的库,在断言库中我偏向于使用should类型的,因为更加的语义化,更符合TDD的阅读习惯。而这段代码看似没有问题,但是运行起来会报错:

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

为什么呢,原因是在第二行、第四行。

const { should } = require('chai');
...
should();

在这样引用了should之后,是无法像刚才代码中那样使用should的,为什么我会写出这样的语法呢?我承认我当时偷懒随便看了篇博客就照猫画虎了,以后一定要跟着官方文档来!!!所以我们这里先纠正错误,正确的代码如下:

const { query } = require('../app/utils/async-db');
const should = require('chai').should();
const mysql = require('mysql');

/**
 * 测试数据库连接的正确状态
 */
describe('mysql connect success state', function() {
  it('should return an array did not have done', function(done) {
    let sql = 'SELECT * FROM `Users`';
    query(sql)
      .then((rows) => {
        rows.should.be.an('array');
        done();
      })
      .catch(err => {
        done(err);
        // throw err;
      });
  });
});

这样,在promise中,在then里直接写断言,之后再跟上done,表示测试完成,就可以成功的完成异步测试,这种方式是done回调的方式。

而还有直接返回promise的方式,写法如下:

/**
 * 测试数据库连接的正确状态
 */
describe('mysql connect success state', function() {
  it('should return an array did not have done', function() {
    let sql = 'SELECT * FROM `Users`';
    return query(sql)
      .then((rows) => {
        rows.should.be.an('array');
      });
  });
});

直接说一下写法的区别吧,在第二行代码的it块内,回调的function中不要再加入done回调的,不然测试程序会一直等待你的done回调,当超时之后就会报错了。而去除done回调之后,直接写返回结果就好了,如果catch到了error,那么直接会被抛出,测试失败。

这两种方法写完,应该还有很多同学觉得这样写非常啰嗦吧,那么我们来看一个chai断言库的中间件,这个中间件可以大大简化promise相关的断言,这个库就是chai-as-promised。这个库中提供了一个最重要的Api就是should.eventually,直接按字面意思去理解这个链式api吧,意味着它会等待promise的最终执行结果,来测试断言。还是刚才的例子,用这个小插件改写完之后是这样的。

const { query } = require('../app/utils/async-db');
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
chai.should();

/**
 * chai-as-promised库的简单使用
 */
describe('Mysql connect', function() {
  // 记得使用chai-as-promised的时候 这里的function不要加 done 参数
  it('should return an array', function() {
    let sql = 'SELECT * FROM `Users`';
    return query(sql).should.eventually.be.an('array');
  });
});

瞬间测试的代码块内只剩下两行代码了,是不是看着分外的爽?稍微学习一下这样的用法,相信异步的单元测试,从此以后对同学们来说就是小菜一碟咯。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • iOS开发——Instruments工具调试

    随着项目的进行,APP的优化必须要尽早的展开了,所以最近自己在学习很多APP的调试技巧,今天我们就来说说Xcode为我们准备的自带的调试工具。

    Originalee
  • 在Yii2框架中使用Redis

    想要在Yii2这个PHP框架中很好的使用redis键值存储,那么首先就要推荐yii2-redis这个官方的Github库。这个库能够很好的帮助我们在Yii2框架...

    Originalee
  • iOS开发——TDD、BDD方法以及Kiwi单元测试框架

    在GitBook上看过一篇文章,一个不写单元测试的程序员不是一个好的攻城狮。坦白的说,在Objective-C这个领域的里,我见过的会主动写单元测试的程序员还是...

    Originalee
  • 深度思考:社交媒体的大数据是否可靠?

      如今,科学家们正越来越多的把目光转向社交媒体,以研究线上及线下的人类行为,例如预测夏季股票市场的大波动。一些数据处理专家指出,使用该种方法处理数据时,研究...

    腾讯研究院
  • 从苦逼到牛逼,详解Linux运维工程师的打怪升级之路

    做运维也快四年多了,就像游戏打怪升级,升级后知识体系和运维体系也相对变化挺大,学习了很多新的知识点。 运维工程师是从一个呆逼进化为苦逼再成长为牛逼的过程,前提在...

    小小科
  • 互联网大公司还在采用过时的技术,为什么?

    许多刚毕业的程序员朋友,都有一个执念,进想要那种规模大一点一的公司,上市的,业内有名的最好。

    一墨编程学习
  • 2018-08-24 大公司为什么还在采用过时的技术!

    https://mp.weixin.qq.com/s/-1VPme1Eb_ItA4ej6_Ghsw

    Albert陈凯
  • 小团队的技术管理

    最近一年左右兼职技术管理的经验试总结,核心理念就是以人为本。 小作坊   小项目的构成往往是一个相对有经验的人作为 leader,带几个毕业生构成一个三五个人...

    晚晴幽草轩轩主
  • scitools Understand安装及入门

    Understand是一个用来进行静态的软件分析、软件度量、软件可视化的工具。他类似于编译器。编译器的输入是代码,输出是可执行文件,而Understand工具的...

    kalifa_lau
  • Apple的Core ML3简介——为iPhone构建深度学习模型(附代码)

    你是Apple的狂热粉丝吗?你用iPhone吗?有没有想过Apple是如何利用机器学习和深度学习来驱动其应用和软件的?

    磐创AI

扫码关注云+社区

领取腾讯云代金券