测试私有方法_Nodejs测试:从0到90(实践篇)

9b6a555fbdbedd91add7b21c10b1748b.png

点击上方蓝字关注我们

本文重点说明Nodejs测试中的相关实践内容,包括nodejs中异步、Promises、私有方法、mock及web等的测试方法。

方法

以下示例均基于mocha.

异步

在异步操作完成时,调用回调(通常是 done) 即可。

describe('User', function() {  describe('#save()', function() {    it('should save without error', function(done) {      var user = new User('Luna');      user.save(done);    });  });});

Mocha的超时设定默认是2s,如果执行的测试超过2s的话,就会报timeout错误。可以修改超时时间,有两种方法:

  • 命令行式

mocha -t 10000
  • API式

describe('async', function () {  this.timeout(10000);    it('async', function (done) {    lib.async(function (result) {      done();    });  });});

Promises

如果异步操作的返回结果是 Promise,可以使用 Chai as Promised(https://www.npmjs.com/package/chai-as-promised)。

'use strict';require('should');require('chai').use(require('chai-as-promised'));describe('test/app/simple/promise.test.js', () => {  it('#Promise', ()=> {    (new Promise(function(resolve) {      resolve(10);    })).should.be.a.Promise();    (10).should.not.be.a.Promise();  });  it('#fulfilled', () => {    return new Promise(resolve => resolve(10))        .should.be.fulfilled();  });  it('#fulfilledWith', () => {    return new Promise((resolve) => resolve(10))        .should.be.fulfilledWith(10);  });  it('#rejected', () => {    return new Promise((resolve, reject) => reject(new Error('boom')))        .should.be.rejected();  });});

私有方法

一般测试只测试接口或公共方法,并不直接测试私有方法。但是如果当私有方法特别多且复杂时,测试私有方法比测试接口或公共方法更直接、有效。

严格上讲,javascript并没有私有方法的概念,这里所讨论的私有方法指未被导出(exports)的方法。

一个简单的盒子,在一个 cal.js 里有一个 add 方法,如下所示:

function add(a, b) {  return a + b;}

此方法为私有方法,无法直接通过 cal 测试,但可以通过 rewire 获取。

rewire adds a special setter and getter to modules so you can modify their behaviour for better unit testing.

获取上面的私有方法,并测试:

it('1 + 1 should equals 2', function () {  let cal = rewire('./cal.js');  let add = cal.__get__('add');  add(1, 1).should.be.eql(2);});

除了获取私有方法,rewire 还可以设置私有变量或方法, 以便测试。

比如有这样一个模块,

// lib/myModules.js// With rewire you can change all these variablesvar fs = require("fs"),    path = "/somewhere/on/the/disk";function readSomethingFromFileSystem(cb) {    console.log("Reading from file system ...");    fs.readFile(path, "utf8", cb);}exports.readSomethingFromFileSystem = readSomethingFromFileSystem;

设置并获取私有变量。

myModule.__set__("path", "/dev/null");myModule.__get__("path"); // = '/dev/null'

还可以用作mock。

var fsMock = {    readFile: function (path, encoding, cb) {        expect(path).to.equal("/somewhere/on/the/disk");        cb(null, "Success!");    }};myModule.__set__("fs", fsMock);

更多用法见 文档。

mock

mock就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。nodejs中常用的mock工具有 muk、sinon 等,以sinon为例简要说明一下其用法。

需要测试的方法:

function once(fn) {    var returnValue, called = false;    return function () {        if (!called) {            called = true;            returnValue = fn.apply(this, arguments);        }        return returnValue;    };}
  • Spy

it("calls the original function", function () {    var spy = sinon.spy();    var proxy = once(spy);    proxy();    assert(spy.called);});
  • Stubs

it("returns the return value from the original function", function () {    var stub = sinon.stub().returns(42);    var proxy = once(stub);    assert.equals(proxy(), 42);});
  • Mocks

it("returns the return value from the original function", function () {    var myAPI = { method: function () {} };    var mock = sinon.mock(myAPI);    mock.expects("method").once().returns(42);    var proxy = once(myAPI.method);    assert.equals(proxy(), 42);    mock.verify();});

更多参考 文档(http://sinonjs.org/)。

web

主要依赖 SuperTest(https://github.com/visionmedia/supertest) ,已在工具部分说明,不再赘述。

更多

持续集成

持续集成(CI, Continuous integration)是一种软件开发实践,即团队开发成员经常集成它们的工作。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

github 上大部分 ci 都是基于 Travis CI。详细接入方案见官方文档,不在此讨论。

代码风格

当写js代码的时候,一个校验工具可以确保一个项目遵循代码规范、帮助我们避免愚蠢的错误。目前比较流行js校验工具有 JSLint、JSHint、JSCS、ESLint, 它们之前的差异比较可以参考 A Comparison of JavaScript Linting Tools,推荐使用 ESLint。

代码风格检查同样也可以集成到 ci,只需要在 ci 命令前追加检查命令即可。以 eslint 为例:

  "scripts": {    // ..    "lint": "eslint .",    "cov": "istanbul cover .",    "ci": "tnpm run lint && TEST_TIMEOUT=60000 istanbul cover ."  },

此时构建会先做代码风格检查,再做单元测试、覆盖率统计,如代码风格检查失败,会直接导致构建中断。

写在后面的

原本计划写一个nodejs的测试参考,帮助还不太了解nodejs测试的同学快速入门,在写的过程中才发现,需要的东西太多,而自己又知道的太少。虽然在一个应用的测试中覆盖率达到了90%,但并不代码在测试方面可以拿到90分。

正如前面写到的,”剩下的10,还有很长的路“,甚至比从0到90更长,唯有不断的学习才能进一步提升,希望自己还能再写个下篇《Nodejs测试:从90到100》。

References

  • Mocha

    http://mochajs.org/

  • QUnit

    http://qunitjs.com/

  • jasmine

    http://jasmine.github.io/

  • Karma

    http://karma-runner.github.io/0.12/index.html

  • JavaScript unit test tools for TDD

    http://stackoverflow.com/questions/300855/javascript-unit-test-tools-for-tdd

  • The Difference Between TDD and BDD

    http://joshldavis.com/2013/05/27/difference-between-tdd-and-bdd/

  • Unit Testing Guidelines,中文

    https://github.com/yangyubo/zh-unit-testing-guidelines

  • A Comparison of JavaScript Linting Tools

写在最后

方凳雅集是由阿里巴巴B系6大BU(1688,ICBU,零售通,AE,企业金融,考拉)共同维护的公众号奥,我们会定期发送优质好文,欢迎扫码关注

e087beb0226bb329ab50bbb141c35b4e.png

求关注

求转发

b88f31eaf08d6f43bd88aeaf47029ea0.png 19d9ca76893c20487ef006ba29c72cb2.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值