• 【Mocha.js 101】钩子函数


    Mocha.js - Hooks

    前情提要

    在上一篇文章《【Mocha.js 101】同步、异步与 Promise》中,我们学会了如何对同步方法、异步回调方法以及 Promise 进行测试。

    在本篇文章中,我们将了解到 Mocha.js 的「钩子函数」(Hooks)。

    钩子(Hooks)

    在测试过程中,我们经常会需要准备一些「桩数据」。集成测试中,通常会选择批量导入一部分模拟数据,或者同步一小部分线上数据,用于测试环境。

    在单元测试中,往往需要在执行测试前,准备相关桩数据,并在测试后将其恢复原样。这便用到了钩子函数。

    Mocha.js 提供了四中钩子函数,分别是 before() , after() , beforeEach() , afterEach() 。

    • before()  将会在所有测试用例执行之前运行,用于同一的桩数据导入等功能;
    • after()  则会在所有测试执行之后运行,用于清理测试环境,删除或回滚相关数据;
    • beforeEach()  将会在每个测试用例执行前执行,可以用于准备测试用例所需的前置条件;
    • afterEach()  将会在每个测试用例之后执行,可以用于准备测试用例所需的后置条件。

    下面,我们来模拟一个场景。首先创建模拟业务逻辑,创建 src/chapter2/User.js 文件,并加入如下代码:

    var stubDB = {};
    
    /**
     * 定义用户类
     *
     * @param name 用户名称
     * @constructor
     */
    function User( name ) {
    }
    
    /**
     * 保存用户.
     *
     * @param name 待保存的用户名称
     */
    User.save = function ( name ) {
        stubDB[ name ] = name;
    };
    
    /**
     * 删除用户.
     *
     * @param name 待删除的用户名称
     */
    User.delete = function ( name ) {
        delete stubDB[ name ];
    };
    
    /**
     * 检查是否包含该用户.
     *
     * @param name 待检查的用户名称
     * @returns {boolean} 如果包含则返回 true, 否则返回 false
     */
    User.contains = function ( name ) {
        return stubDB[ name ] != null;
    };
    
    // Export the User class.
    module.exports = User;

    如代码所示,User  类提供了三个方法,save  用于保存用户,delete  用于删除用户,contains  用于判断用户是否存在。

    接下来,让我们创建 test/chapter2/hooks.js  文件,并加入测试代码:

    var should = require( 'should' );
    var User   = require( '../../src/chapter2/User' );
    
    // 描述 User 行为
    describe( 'User', function () {
    
        // 在执行所有测试前, 执行 before(), 添加桩数据
        before( function () {
            User.save( 'luochuan' );
        } );
    
        // 在执行每个测试前, 执行 beforeEach(), 添加桩数据
        beforeEach( function () {
            User.save( 'hermit' );
        } );
    
        // 描述 User.save 行为
        describe( '#save', function () {
    
            // 保存 robert 用户成功.
            it( 'Save "robert" successfully.', function () {
                User.save( 'robert' );
            } );
        } );
    
        // 描述 User.contains 行为
        describe( '#contains', function () {
    
            // 应该存在 Hermit 用户
            it( '"Hermit" already exists.', function () {
                User.contains( 'hermit' ).should.be.exactly( true );
            } );
    
            // 应该不存在 Martin 用户
            it( '"Martin" not exists.', function () {
                User.contains( 'Martin' ).should.be.exactly( false );
            } );
        } );
    
        // 在执行完每个测试后, 清空桩数据.
        afterEach( function () {
            User.delete( 'hermit' );
        } );
    
    
        // 在执行完每个测试后, 清空桩数据.
        after( function () {
            User.delete( 'luochuan' );
        } );
    } );

    测试代码中,我们定义了 before() ,after() ,beforeEach()  和 afterEach() 。接下来,我们来执行测试,看看输出结果:

    $ mocha test/chapter2/hooks.js
    
      User
        #save
          ✓ Save "robert" successfully.
        #contains
          ✓ "Hermit" already exists.
          ✓ "Martin" not exists.
    
    
      3 passing (9ms)
    

    我们将会发现,测试三个测试均已通过。所以证明,相关钩子函数已经正确执行,并插入了我们需要的桩数据。

    描述钩子函数

    在之前的文章中,我们介绍了 describe()  函数。通过 describe()  函数,我们描述了对一个测试用例的预期。

    同样,对于钩子函数,我们也能够添加相应的描述信息。

    • before( description, callback )
    • after( description, callback )
    • beforeEach( description, callback )
    • afterEach( description, callback )

    我们只需要指定钩子函数的 description 参数,即可描述该行为。接下来,让我们创建 test/chapter2/describeHooks.js ,来试试描述钩子函数:

    var should = require( 'should' );
    var User   = require( '../../src/chapter2/User' );
    
    // 描述 User 行为
    describe( 'User', function () {
    
        // 在执行所有测试前, 执行 before(), 添加桩数据
        before( 'Before all tests.', function () {
            User.save( 'hermit' );
        } );
    
        // 在执行每个测试前, 执行 beforeEach(), 添加桩数据
        beforeEach( 'Before each test case.', function () {
        } );
    
        // 描述 User.save 行为
        describe( '#delete', function () {
    
            // 删除 hermit 用户成功.
            it( 'Delete user successfully.', function () {
                User.delete( 'hermit' );
            } );
        } );
    
        // 在执行完每个测试后, 清空桩数据.
        afterEach( 'After each test case.', function () {
        } );
    
        // 在执行完每个测试后, 清空桩数据.
        after( 'After all tests.', function () {
            User.delete( 'hermit' );
        } );
    } );

    如代码高亮处所示,我们为钩子函数添加了描述信息。

    接下来,让我们执行测试:

    $ mocha test/chapter2/describeHook.js
    
      User
        #delete
          ✓ Delete user successfully.
    
    
      1 passing (7ms)
    

    做到这里,大家会感到很疑惑:和上面的输出并没有什么区别啊?

    其实,描述信息是为了方便问题定位的。我们来模拟一下 beforeEach()  函数抛出异常的情况:

    beforeEach( 'Before each test case.', function () {
        throw Error();
    } );

    同样,我们执行测试:

    $ mocha test/chapter2/describeHook.js
    
      User
        #delete
          1) "before each" hook: Before each test case. for "Delete user successfully."
    
    
      0 passing (8ms)
      1 failing
    
      1) User "before each" hook: Before each test case. for "Delete user successfully.":
         
      rror
          at Error (native)
          at Context.<anonymous> (test/chapter2/describeHook.js:14:15)
    
    

    这样,我们便看到,我们所定义的 beforeEach()  钩子执行失败。具体是 "before each" hook: Before each test case. for "Delete user successfully."

    异步钩子函数

    我们在上一篇文章中,介绍了异步测试的执行方式。钩子函数也同样支持异步执行,并且以相同的方法支持——done 参数。所以,在此我们利用上一篇文章的Ajax,做一个非常简单的示例:

    describe( 'Ajax', function () {
    
        beforeEach( function ( done ) {
            Ajax.load( 'url', function () {
                done();
            } );
        } );
    } );

    Root钩子(Root-level Hooks)

    将钩子函数写在 describe()  方法以外,将会作用于所有的测试用例。比如 beforeEach()  方法,如果写在了 describe()  方法以外,将会在所有的测试用例执行前执行该方法。

    总结

    本文介绍了 Mocha.js 如何使用钩子函数,模拟测试所需桩数据及模拟环境。Mocha.js 通过 before(),after(),beforeEach(),afterEach() 四个钩子函数,允许在测试用例前后执行相关代码。


    本文以 CC BY-NC-SA 3.0 CN 协议共享,转载、共享及二次创作时请保留原文出处及链接,请勿用于商业用途。

    本文链接:http://litecodes.com/dev/frontend/mocha-101-hooks/

  • 相关阅读:
    (网络流)ACM Computer Factory --POJ --3436
    (小数化分数)小数化分数2 -- HDU --1717
    (小数化分数)小数化分数2 --HDU --1717
    (网络流 模板 Dinic) Drainage Ditches --POJ --1273
    (网络流 模板 Edmonds-Karp)Drainage Ditches --POJ --1273
    (匹配)Oil Skimming -- hdu --4185
    (匹配 二维建图) Antenna Placement --POJ --3020
    (匹配)Antenna Placement --POJ --3020
    将截断字符串或二进制数据【转】
    C#中Abstract和Virtual 【转】
  • 原文地址:https://www.cnblogs.com/rainisic/p/mocha-101-hooks.html
Copyright © 2020-2023  润新知