【问题标题】:Sinon to unit test 'catch' statementSinon 对“catch”语句进行单元测试
【发布时间】:2016-11-30 06:27:16
【问题描述】:

我有一个简单的函数,例如;

module.exports = {
  fetchUser:function(myUserId) {
    return new Promise((resolve, reject) => {
      this.getUser(myUserId)
        .then(user => {
          // do logic // then return user

          return user;
        })
        .then(resolve)
        .catch(err => {
          // whoops there has been an error

          let error = { error: 'My Error' };

          reject(error);
        });
    });
  }
};

我想对resolvereject 结果进行单元测试。

一个简单的chai 测试将是;

var expect = require('chai').expect;
var user = require('./user');

describe('User module', function() {
  it('test fetchUser', function() {
    let _user = user.fetchUser('abc123');

    return _user
      .then(user => {
        expect(data).to.be.an('object');
      });
  });

使用sinon 或其他库,我怎样才能让fetchUser 函数抛出reject 错误?

【问题讨论】:

    标签: node.js unit-testing sinon chai


    【解决方案1】:

    使用 MochaChaiSinon 可以使用存根方法 getUser 来实现。

    const User = require("./fetchUserModule");
    
    describe('User module', () => {
        beforeEach(() => User.getUser = sinon.stub());
    
        afterEach(() => User.getUser.reset());
    
        it('returns user if `getUser` returns data', () => {
            const user = {name: 'John'};
            User.getUser.withArgs("abc123").returns(Promise.resolve(user));
    
            return User.fetchUser("abc123").then(result => {
                expect(result).to.equal(user)
            }).catch(error => {
                expect(error).to.be.undefined;
            })
        });
    
        it('throws error if `getUser` is rejected', () => {
            User.getUser.withArgs("abc123").returns(Promise.reject());
    
            return User.fetchUser("abc123").then(result => {
                expect(result).to.be.undefined;
            }).catch(err => {
                expect(err).to.eql({error: 'My Error'})
            })
        });
    });
    

    【讨论】:

    • 谢谢。如果我以这种方式设置测试,它实际上不会进入我的 catch 代码块,是吗?存根只是伪造响应以匹配我捕获的错误。
    • 是的,它进入catch 语句,因为错误等于{error: 'My Error'}。您还需要什么来证明它有效?
    • 谢谢,我只是在检查,我还没有完全理解存根。我会测试一下。
    • 我在发布答案之前对其进行了测试 - 它按预期工作......
    【解决方案2】:

    从“逻辑”中可能引发错误的任何内容开始。

    如果不是,您需要存根 this.getUser 来拒绝或抛出错误,而不是返回数据。 sinon-as-promised 修补 sinon.stub 以包括 .resolves.rejects 承诺助手。

    const sinon  = require('sinon')
    require('sinon-as-promised')
    

    为失败测试设置存根。

    before(function(){
      sinon.stub(user, 'getUser').rejects(new Error('whatever'))
    })
    
    after(function(){
      user.getUser.restore()
    })
    

    然后要么捕获.fetchUser 错误,要么使用chai-as-promised 获取一些糖。

    it('test fetchUser', function() {
      return user.fetchUser('abc123')
        .then(()=> expect.fail('fetchUser should be rejected'))
        .catch(err => {
          expect(err.message).to.eql('whatever')
        })
    })
    
    it('test fetchUser', function() {
      return expect(user.fetchUser('abc123')).to.be.rejectedWith(Error)
    })
    

    或者async如果你生活在新世界

    it('test fetchUser', async function() {
      try { 
        await user.fetchUser('abc123')
        expect.fail('fetchUser should be rejected'))
      } catch(err) {
        expect(err.message).to.eql('whatever')
      }
    })
    

    作为旁注,您无需在 new Promise 中包装已经返回承诺的内容,并且在链接多个 .catch 处理程序时要小心丢失错误信息。

    fetchUser: function (myUserId) {
      return this.getUser(myUserId)
        .then(user => {
          //logic
          return user
        })
        .catch(err => {
          let error = new Error('My Error')
          error.original = err
          reject(error)
        });
    }
    

    【讨论】:

    • 谢谢马特。我没有意识到最后一点,我将更新我的代码库。
    猜你喜欢
    • 2020-06-21
    • 2020-06-08
    • 2015-06-15
    • 1970-01-01
    • 2020-08-13
    • 2016-12-21
    • 2013-12-19
    • 2021-07-16
    • 2021-03-15
    相关资源
    最近更新 更多