尽可能去除依赖,或者使用一些依赖替身(谨慎使用),包括 fake, mock, stub, spy.
参考 karma 配置 新建一个项目 dependence
- 测试 createURL
# create-url-test.js
describe('create-url test', function() {
it('should return proper url given lat and lon', function() {
var latitude = -33.857;
var longitude = 151.215;
var url = createURL(latitude, longitude);
expect(url).to.be.eql('http://maps.google.com?q=-33.857,151.215');
});
});
# locateme.js
var createURL = function(latitude, longitude) {
if (latitude && longitude)
return 'http://maps.google.com?q=' + latitude + ',' + longitude;
return '';
};
- 接着添加正向、反向测试
......
-
fake: 适用于测试单不能用于生产环境的实现;
-
stub:它并不是真正的实现,但被调用时可以快速返回预设数据;能用来验证依赖返回结果后代码的行为;
-
mock: 与 stub 类似,mock 也可以返回预设数据;
-
spy: 代理真实的依赖。
-
依赖注入
依赖注入是用测试替身代替依赖的一种流行、通用的技术;不是被测试代码依赖,而是依赖被注入
# setlocation-test.js
describe('setLocation test', function() {
it('should set the URL into location of window', function() {
var windowStub = {};
var url = 'http://example.com';
setLocation(windowStub, url);
expect(windowStub.location).to.be.eql(url);
});
});
# locateme.js
var setLocation = function(window, url) {
window.location = url;
};
替换依赖对象的 windowStub 是个 stub,不是 mock;
想要验证 locate 函数调用了 getCurrentPosition 函数,
但不能再测试中 让 locate 调用真正的定位函数,这样会很耗时,无法预测
因为我们验证 locate 函数是否调用了它的依赖函数,应该使用 mock 而不是 stub,
# locateme.js
var locate = function() {
navigator.geolocation.getCurrentPosition(onSuccess, onError);
};
/*
var onError = function() {}
var onSuccess = function() {}
*/
var onError = function(error) {
document.getElementById('error').innerHTML = error.message;
};
/*
var onSuccess = function(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
createURL(latitude, longitude);
}
*/
var onSuccess = function(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var url = createURL(latitude, longitude);
setLocation(window, url);
};
sinon 提供一些函数来创建不同类型的测试替身,
- 安装依赖
npm i --save-dev karma-sinon-chai sinon sinon-chai karma-sinon
- 配置 karma
frameworks: ['mocha', 'chai', 'sinon', 'sinon-chai'],
- 创建 sandbox
var sandbox;
beforeEach(function() {
sandbox = sinon.sandbox.create();
});
afterEach(function() {
sandbox.restore();
});