【问题标题】:Running Mocha setup before each suite rather than before each test在每个套件之前而不是在每个测试之前运行 Mocha 设置
【发布时间】:2014-11-24 06:24:06
【问题描述】:

使用 NodeJS 和 Mocha 进行测试。我想我了解 before() 和 beforeEach() 的工作原理。问题是,我想添加一个在每个“描述”之前而不是在每个“它”之前运行的设置脚本。

如果我使用before(),它将在整个套件中只运行一次,如果我使用beforeEach(),它将在每次测试之前执行,所以我试图找到一个中间立场。

所以,如果这是我的测试文件:

require('./setupStuff');

describe('Suite one', function(){
  it('S1 Test one', function(done){
    ...
  });
  it('S1 Test two', function(done){
    ...
  });
});
describe('Suite two', function(){
  it('S2 Test one', function(done){
    ...
  });
});

我想让“setupStuff”包含一个在“套件一”和“套件二”之前运行的函数

或者,换句话说,在“S1 测试一”和“S2 测试一”之前,但不在“S1 测试二”之前。

可以吗?

【问题讨论】:

    标签: javascript node.js mocha.js


    【解决方案1】:

    没有类似于beforeEachbefore 的调用可以满足您的需求。但它不是必需的,因为您可以这样做:

    function makeSuite(name, tests) {
        describe(name, function () {
            before(function () {
                console.log("shared before");
            });
            tests();
            after(function () {
                console.log("shared after");
            });
        });
    }
    
    makeSuite('Suite one', function(){
      it('S1 Test one', function(done){
          done();
      });
      it('S1 Test two', function(done){
          done();
      });
    });
    
    makeSuite('Suite two', function(){
      it('S2 Test one', function(done){
        done();
      });
    });
    

    【讨论】:

    • 这很好用(当不使用skiponly 时),如果你想添加skiponly(在describe 级别),你知道这将如何工作?
    • 我也有同样的想法,但不幸的是,Jetbrains IDE 会将文件识别为 JS 而不是 MOCHA。 :-/
    • 如何将before 中实例化的值传递给所有测试?理想情况下,您将在之前运行要测试的函数,然后使用一组 it 块来评估返回值和状态。除了beforeafter 的基本集之外,您可能还需要为每个套件提供更多自定义beforeafter 挂钩。 beforeEachafterEach 不要删减它,因为它们只对 it 块而不是 describe 块进行操作。
    【解决方案2】:

    你也可以用这种更灵活的方式来做:

    require('./setupStuff');
    
    describe('Suite one', function(){
      loadBeforeAndAfter(); //<-- added
      it('S1 Test one', function(done){
        ...
      });
      it('S1 Test two', function(done){
        ...
      });
    });
    describe('Suite two', function(){
      loadBeforeAndAfter();//<-- added
      it('S2 Test one', function(done){
        ...
      });
    });
    describe('Suite three', function(){
      //use some other loader here, before/after, or nothing
      it('S3 Test one', function(done){
        ...
      });
    });
    
    function loadBeforeAndAfter() {
      before(function () {
        console.log("shared before");
      });
      after(function () {
        console.log("shared after");
      });
    }
    

    【讨论】:

    • 我开始准备答案,虽然 Louis 有完美的解决方案,但它阻止了我使用 skiponly。这个解决方案和他的一样,但是它允许我继续使用skiponly
    【解决方案3】:

    我发现这种方法对我有用,它修补了所有描述套件。

    function suitePatches()
    {
        before(function()
        {
            // before suite behaviour
        });
        after(function()
        {
            // after suite behaviour
        });
    }
    
    let origDescribe = describe;
    describe = function(n,tests)
    {
        origDescribe(n,function()
        {
            suitePatches();
            tests.bind(this)();
        });
    }
    let origOnly = origDescribe.only;
    describe.only = function(n,tests)
    {
        origOnly(n,function()
        {
            suitePatches();
            tests.bind(this)();
        });
    }
    describe.skip = origDescribe.skip;
    

    与其他答案的不同之处在于:

    • 使用bind 调用tests 确保如果他们调用this 上的函数,例如this.timeout(1000),仍然可以工作。
    • 处理.skip.only 意味着您仍然可以使用您套件上的那些,例如describe.skip 来暂时禁止套件。
    • 按名称替换describe 函数可以减少侵入性注入。
      • 这可能不符合每个人的口味,在这种情况下,显然可以使用替代函数名称,同时仍然使用正确处理调用 testsonlyskip

    【讨论】:

      【解决方案4】:

      @ya_dimon 的解决方案是有效的,但是如果你想包装itcallback 函数,并传递参数如下。

      function dynamicTestCase(a) {
        return function(done){ console.log(a); } // a is undefined
      }
      
      describe("test", function(){
          before(function(){
              a = 8;
          });
          it('POST /verifications receiveCode', dynamicTestCase(a)); // a is undefined
      })
      

      为什么a 未定义?因为itdescribe 中的before 之前执行。在这种情况下,@ya_dimon 的解决方案无法正常工作,但您可以按照以下方式巧妙地完成它。

      function dynamicTestCase(a) {
        return function(done){ console.log(a()); } // a is delayed pass! a = 8, remember change a to a()
      }
      
      describe("test", function(){
          before(function(){
              a = 8;
          });
          it('POST /verifications receiveCode', dynamicTestCase(() => a)); // a is delayed pass!
      })
      

      希望这有助于弄清楚执行顺序。

      【讨论】:

        猜你喜欢
        • 2017-05-02
        • 1970-01-01
        • 2018-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-11
        • 2012-08-07
        • 2013-09-27
        相关资源
        最近更新 更多