我正在尝试使用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
在阅读代码时,我发现了一些可以改进的方面。对于源代码,我们可以删除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有我们可以使用的resolves
和rejects
方法。参考: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);
}
});
});
希望能帮助到你。