代码之家  ›  专栏  ›  技术社区  ›  Sachihiro

chai正在测试不应抛出typeerror的未定义项[重复]

  •  0
  • Sachihiro  · 技术社区  · 6 年前

    我很难拿到柴的 expect.to.throw 在node.js应用程序的测试中工作。测试在抛出的错误上一直失败,但是如果我在try-and-catch中包装测试用例,并对捕获的错误进行断言,那么它就工作了。

    期望投掷 不是像我想的那样工作吗?

    it('should throw an error if you try to get an undefined property', function (done) {
      var params = { a: 'test', b: 'test', c: 'test' };
      var model = new TestModel(MOCK_REQUEST, params);
    
      // neither of these work
      expect(model.get('z')).to.throw('Property does not exist in model schema.');
      expect(model.get('z')).to.throw(new Error('Property does not exist in model schema.'));
    
      // this works
      try { 
        model.get('z'); 
      }
      catch(err) {
        expect(err).to.eql(new Error('Property does not exist in model schema.'));
      }
    
      done();
    });
    

    失败:

    19 passing (25ms)
      1 failing
    
      1) Model Base should throw an error if you try to get an undefined property:
         Error: Property does not exist in model schema.
    
    0 回复  |  直到 7 年前
        1
  •  300
  •   Louis    12 年前

    必须将函数传递给 expect . 这样地:

    expect(model.get.bind(model, 'z')).to.throw('Property does not exist in model schema.');
    expect(model.get.bind(model, 'z')).to.throw(new Error('Property does not exist in model schema.'));
    

    你这样做,是为了 期待 这个 结果 召唤的 model.get('z') . 但要测试是否抛出了某些内容,必须将函数传递给 期待 哪一个 期待 会自称。这个 bind 上面使用的方法创建一个新函数,当调用该函数时将调用 model.get 具有 this 设置为的值 model 第一个参数设置为 'z' .

    很好的解释 绑定 可以找到 here .

        2
  •  157
  •   Community Mohan Dere    8 年前

    AS this answer says ,您也可以将代码包装在匿名函数中,如下所示:

    expect(function(){
        model.get('z');
    }).to.throw('Property does not exist in model schema.');
    
        3
  •  78
  •   Daniel T.    9 年前

    如果您已经在使用ES6/ES2015,那么您还可以使用箭头函数。它基本上与使用普通匿名函数相同,但更短。

    expect(() => model.get('z')).to.throw('Property does not exist in model schema.');
    
        4
  •  62
  •   Charles Merriam    8 年前

    这个问题有很多重复的地方,包括没有提到chai断言库的问题。以下是收集到的基本信息:

    断言必须调用函数,而不是立即求值。

    assert.throws(x.y.z);      
       // FAIL.  x.y.z throws an exception, which immediately exits the
       // enclosing block, so assert.throw() not called.
    assert.throws(()=>x.y.z);  
       // assert.throw() is called with a function, which only throws
       // when assert.throw executes the function.
    assert.throws(function () { x.y.z });   
       // if you cannot use ES6 at work
    function badReference() { x.y.z }; assert.throws(badReference);  
       // for the verbose
    assert.throws(()=>model.get(z));  
       // the specific example given.
    homegrownAssertThrows(model.get, z);
       //  a style common in Python, but not in JavaScript
    

    您可以使用任何断言库检查特定错误:

    Node

      assert.throws(() => x.y.z);
      assert.throws(() => x.y.z, ReferenceError);
      assert.throws(() => x.y.z, ReferenceError, /is not defined/);
      assert.throws(() => x.y.z, /is not defined/);
      assert.doesNotThrow(() => 42);
      assert.throws(() => x.y.z, Error);
      assert.throws(() => model.get.z, /Property does not exist in model schema./)
    

    Should

      should.throws(() => x.y.z);
      should.throws(() => x.y.z, ReferenceError);
      should.throws(() => x.y.z, ReferenceError, /is not defined/);
      should.throws(() => x.y.z, /is not defined/);
      should.doesNotThrow(() => 42);
      should.throws(() => x.y.z, Error);
      should.throws(() => model.get.z, /Property does not exist in model schema./)
    

    Chai Expect

      expect(() => x.y.z).to.throw();
      expect(() => x.y.z).to.throw(ReferenceError);
      expect(() => x.y.z).to.throw(ReferenceError, /is not defined/);
      expect(() => x.y.z).to.throw(/is not defined/);
      expect(() => 42).not.to.throw();
      expect(() => x.y.z).to.throw(Error);
      expect(() => model.get.z).to.throw(/Property does not exist in model schema./);
    

    您必须处理“转义”测试的异常

    it('should handle escaped errors', function () {
      try {
        expect(() => x.y.z).not.to.throw(RangeError);
      } catch (err) {
        expect(err).to.be.a(ReferenceError);
      }
    });
    

    一开始这看起来很混乱。就像骑自行车一样,一旦它发出“咔嚓”声,它就会永远发出“咔嚓”声。

        5
  •  4
  •   Michal Miky Jankovský    7 年前

    示例来自 doc …;)

    因为你依赖 语境 :

    • 当函数被 投掷
    • 它不可能知道这是什么

    必须使用以下选项之一:

    • 另一个函数内部的方法或函数调用
    • 绑定 语境

      // wrap the method or function call inside of another function
      expect(function () { cat.meow(); }).to.throw();  // Function expression
      expect(() => cat.meow()).to.throw();             // ES6 arrow function
      
      // bind the context
      expect(cat.meow.bind(cat)).to.throw();           // Bind
      
        6
  •  1
  •   SeanOlson    7 年前

    另一个可能的实现,比.bind()解决方案更麻烦,但是一个有助于说明expect()的点的实现需要一个提供 this 在所覆盖函数的上下文中,可以使用 call() 例如,

    expect(function() {model.get.call(model, 'z');}).to.throw('...');