zoukankan      html  css  js  c++  java
  • 【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/

    Cnblogs 同步更新我的原始博客。

  • 相关阅读:
    使用javap分析Java的字符串操作
    使用javap深入理解Java整型常量和整型变量的区别
    分享一个WebGL开发的网站-用JavaScript + WebGL开发3D模型
    Java动态代理之InvocationHandler最简单的入门教程
    Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)
    Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)
    Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)
    Java实现 LeetCode 541 反转字符串 II(暴力大法)
    Java实现 LeetCode 541 反转字符串 II(暴力大法)
    Java实现 LeetCode 541 反转字符串 II(暴力大法)
  • 原文地址:https://www.cnblogs.com/litecodes/p/mocha-101-hooks.html
Copyright © 2011-2022 走看看