【问题标题】:Unit testing in Loopback with Mocha, Sinon and Chai使用 Mocha、Sinon 和 Chai 在 Loopback 中进行单元测试
【发布时间】:2019-02-14 07:29:26
【问题描述】:

我正在尝试对 Loopback 中的自定义方法进行单元测试。 该方法本身会清除所有用户数据给定参数。

module.exports = function(User) {
  User.clearData = async function(options) {
    const cityId = options.accessToken.cityId;

    const deleteUserData = () => {
      return User.destroyAll({cityId: cityId}, options).catch(error => {
        console.log('Error deleting user', error);
        throw error;
      });
    };

    await deleteUserData();
  };
};

我之前做过的事情是这样的:

const sinon = require('sinon');
const {expect} = require('chai');

const clearDataUser = require('../clear-data');

describe('User clear data', ()=>{
  let spy,
    User;

  const options = {
    accessToken: {
      cityId: 1,
    },
  };

  beforeEach(()=>{
    spy = sinon.spy();
    User = {
      destroyAll: spy,
    };
  });

  it('should call destroyAll', () => {
    clearDataUser(User);
    User.destroyAll({cityId: options.accessToken.cityId}, options);
    expect(spy.callCount).to.eq(1);
  });
});

这将只测试destroyAll 是否被调用。有没有办法测试catch 条件?我也在使用async/await,所以这也可以考虑吗? _____________________________________编辑_____________________________________

我把它改了一下,看起来像:

  it('should call destroyAll', async() => {
    clearDataUser(User);
    const deleteUserData = () => {
      return User.destroyAll({cityId: options.accessToken.cityId}, options);
    };

    await deleteUserData();
    expect(spy.callCount).to.eq(1);
  });

但是,如果我尝试添加 .catch(error => { expect(error).to.not.equal('undefined'); });,我会得到 TypeError: Cannot read property 'catch' of undefined

【问题讨论】:

    标签: unit-testing mocha.js sinon chai loopback


    【解决方案1】:

    在阅读代码时,我发现了一些可以改进的地方。对于源代码,我们可以去掉deleteUserData函数。另外,您打算通过添加User.clearData 来改变User 对象吗?

    这是我所做的改进。

    // clear-data.js
    
    module.exports = function(User) {
      const clearData = function(options) { // no need `async`
        const cityId = options.accessToken.cityId;
    
        // just return User.destroyAll directly
        return User.destroyAll({cityId: cityId}, options).catch(error => {
          console.log('Error deleting user', error);
          throw error;
        });
      };
    
      return {
        clearData // this is the function that we should test 
      }
    };
    

    对于测试,我不确定我们为什么要测试 User.destroyAll,因为我希望我们在这里测试 clearData 函数。我们必须存根User.destroyAll 来解决或拒绝它(因此将执行catch)。

    诗乃有resolvesrejects 可以使用的方法。参考:https://sinonjs.org/releases/v2.0.0/stubs/

    const sinon = require('sinon');
    const {expect} = require('chai');
    
    const src = require('../clear-data');
    
    describe('User clear data', () => {
      let stubDestroyAll,
          User;
    
      const options = {
        accessToken: {
          cityId: 1,
        },
      };
    
      beforeEach(()=>{
        stubDestroyAll = sinon.stub(); // mock this so we can resolve or reject the method 
      });
    
      afterEach(() => {
        sinon.restore();
      });
    
      it('should call destroyAll', async () => {
        User = {
          destroyAll: stubDestroyAll.resolves(), 
        };
        const func = src(User);    
        await func.clearData(options);
        expect(stubDestroyAll.callCount).to.eq(1);
      });
    
      it('should catch error', async () => {
        User = {
          destroyAll: stubDestroyAll.rejects(), // reject so it will go to catch
        };
        const func = src(User);
    
        try {
          await func.clearData(options);            
          expect(true).to.be(false); // extra guard if it doesn't go to catch, the test will fail
        } catch(err) {
          expect(stubDestroyAll.callCount).to.eq(1);      
        }
      });
    });
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 2021-09-27
      • 2016-05-26
      • 2023-04-11
      • 2019-02-03
      • 2015-05-16
      • 2018-11-05
      • 2017-06-09
      • 2023-03-22
      • 2015-10-01
      相关资源
      最近更新 更多