使用 sinon 测试内部函数
Testing an inside function with sinon
我需要测试一个名为 "cache" 的函数。它是一个函数包装器,它接受一个函数并根据应用于该函数的参数缓存其结果。
这就是我实现功能的方式
const cache = (func) => {
let cache = {};
let stringFromArgs;
return (...args) => {
let n = args[0];
if (stringFromArgs === JSON.stringify(args)) {
return cache[n];
} else {
stringFromArgs = JSON.stringify(args)
cache[n] = func(...args);
return cache[n];
}
}
}
这就是它的工作原理:
let complexFunction = function(arg1, arg2) {
return arg1 + arg2;
};
let cachedFunction = cache(complexFunction);
cachedFunction(1, 2); // complex function should be executed
cachedFunction(1, 2); // complex function should not be invoked again,
// instead the cached result should be returned
cachedFunction(1, 5); // should be executed, because the method wasn't invoked before with these arguments
当使用相同参数调用函数 cachedFunction 两次时,该内部函数应该只调用一次。第二次结果应该来自缓存。我需要使用 sinon.js 来测试它。或者也许还有另一种方法可以测试它?
单元测试解决方案如下:
cache.js
:
const cache = (func) => {
let cache = {};
let stringFromArgs;
return (...args) => {
let n = args[0];
if (stringFromArgs === JSON.stringify(args)) {
return cache[n];
} else {
stringFromArgs = JSON.stringify(args);
cache[n] = func(...args);
return cache[n];
}
};
};
module.exports = cache;
cache.test.js
:
const cache = require('./cache');
const sinon = require('sinon');
const { expect } = require('chai');
describe('62426207', () => {
it('should call complex function', () => {
let complexFunction = sinon.stub().callsFake((arg1, arg2) => {
return arg1 + arg2;
});
let cachedFunction = cache(complexFunction);
cachedFunction(1, 2);
sinon.assert.calledWith(complexFunction, 1, 2);
sinon.assert.calledOnce(complexFunction);
});
it('should not call complex function again', () => {
let complexFunction = sinon.stub().callsFake((arg1, arg2) => {
return arg1 + arg2;
});
let cachedFunction = cache(complexFunction);
cachedFunction(1, 2);
let ret = cachedFunction(1, 2);
expect(ret).to.be.equal(3);
sinon.assert.calledWith(complexFunction, 1, 2);
sinon.assert.calledOnce(complexFunction);
});
it('should call complex function if arguments are different', () => {
let complexFunction = sinon.stub().callsFake((arg1, arg2) => {
return arg1 + arg2;
});
let cachedFunction = cache(complexFunction);
let ret1 = cachedFunction(1, 2);
expect(ret1).to.be.equal(3);
let ret2 = cachedFunction(1, 5);
expect(ret2).to.be.equal(6);
sinon.assert.calledWith(complexFunction, 1, 2);
sinon.assert.calledWith(complexFunction, 1, 5);
sinon.assert.calledTwice(complexFunction);
});
});
100% 覆盖率的单元测试结果:
62426207
✓ should call complex function
✓ should not call complex function again
✓ should call complex function if arguments are different
3 passing (18ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
cache.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
我需要测试一个名为 "cache" 的函数。它是一个函数包装器,它接受一个函数并根据应用于该函数的参数缓存其结果。
这就是我实现功能的方式
const cache = (func) => {
let cache = {};
let stringFromArgs;
return (...args) => {
let n = args[0];
if (stringFromArgs === JSON.stringify(args)) {
return cache[n];
} else {
stringFromArgs = JSON.stringify(args)
cache[n] = func(...args);
return cache[n];
}
}
}
这就是它的工作原理:
let complexFunction = function(arg1, arg2) {
return arg1 + arg2;
};
let cachedFunction = cache(complexFunction);
cachedFunction(1, 2); // complex function should be executed
cachedFunction(1, 2); // complex function should not be invoked again,
// instead the cached result should be returned
cachedFunction(1, 5); // should be executed, because the method wasn't invoked before with these arguments
当使用相同参数调用函数 cachedFunction 两次时,该内部函数应该只调用一次。第二次结果应该来自缓存。我需要使用 sinon.js 来测试它。或者也许还有另一种方法可以测试它?
单元测试解决方案如下:
cache.js
:
const cache = (func) => {
let cache = {};
let stringFromArgs;
return (...args) => {
let n = args[0];
if (stringFromArgs === JSON.stringify(args)) {
return cache[n];
} else {
stringFromArgs = JSON.stringify(args);
cache[n] = func(...args);
return cache[n];
}
};
};
module.exports = cache;
cache.test.js
:
const cache = require('./cache');
const sinon = require('sinon');
const { expect } = require('chai');
describe('62426207', () => {
it('should call complex function', () => {
let complexFunction = sinon.stub().callsFake((arg1, arg2) => {
return arg1 + arg2;
});
let cachedFunction = cache(complexFunction);
cachedFunction(1, 2);
sinon.assert.calledWith(complexFunction, 1, 2);
sinon.assert.calledOnce(complexFunction);
});
it('should not call complex function again', () => {
let complexFunction = sinon.stub().callsFake((arg1, arg2) => {
return arg1 + arg2;
});
let cachedFunction = cache(complexFunction);
cachedFunction(1, 2);
let ret = cachedFunction(1, 2);
expect(ret).to.be.equal(3);
sinon.assert.calledWith(complexFunction, 1, 2);
sinon.assert.calledOnce(complexFunction);
});
it('should call complex function if arguments are different', () => {
let complexFunction = sinon.stub().callsFake((arg1, arg2) => {
return arg1 + arg2;
});
let cachedFunction = cache(complexFunction);
let ret1 = cachedFunction(1, 2);
expect(ret1).to.be.equal(3);
let ret2 = cachedFunction(1, 5);
expect(ret2).to.be.equal(6);
sinon.assert.calledWith(complexFunction, 1, 2);
sinon.assert.calledWith(complexFunction, 1, 5);
sinon.assert.calledTwice(complexFunction);
});
});
100% 覆盖率的单元测试结果:
62426207
✓ should call complex function
✓ should not call complex function again
✓ should call complex function if arguments are different
3 passing (18ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
cache.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------