使用Mocha,Sinon和Chai在Loopback中进行单元测试

问题描述 投票:0回答:1

我正在尝试使用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 sinon chai loopback
1个回答
0
投票

在阅读代码时,我发现了一些可以改进的方面。对于源代码,我们可以删除deleteUserData函数。另外,你打算通过添加User来改变User.clearData对象是什么意思?

这是我所做的改进。

// 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存根以解决承诺或拒绝承诺(因此将执行捕获)。

Sinon有我们可以使用的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);      
    }
  });
});

希望能帮助到你。

© www.soinside.com 2019 - 2024. All rights reserved.