Ant*_*ile 90 javascript unit-testing mocking local-storage sinon
那里有没有图书馆要模拟localStorage
?
我一直在使用Sinon.JS进行大多数其他javascript 模拟,并发现它真的很棒.
我的初步测试显示localStorage拒绝在firefox(sadface)中分配,所以我可能需要某种黑客攻击:/
我现在的选择(如我所见)如下:
??????
您如何看待这些方法,您认为还有其他更好的方法吗?无论哪种方式,我都会把最终制作的"库"放在github上,以获得开源的优点.
And*_*rle 120
以下是使用Jasmine模拟它的简单方法:
beforeEach(function () {
var store = {};
spyOn(localStorage, 'getItem').andCallFake(function (key) {
return store[key];
});
spyOn(localStorage, 'setItem').andCallFake(function (key, value) {
return store[key] = value + '';
});
spyOn(localStorage, 'clear').andCallFake(function () {
store = {};
});
});
Run Code Online (Sandbox Code Playgroud)
如果要在所有测试中模拟本地存储,请在测试beforeEach()
的全局范围内声明上面显示的函数(通常的位置是specHelper.js脚本).
a8m*_*a8m 48
只需模拟全局localStorage/sessionStorage(它们具有相同的API)即可满足您的需求.
例如:
// Storage Mock
function storageMock() {
var storage = {};
return {
setItem: function(key, value) {
storage[key] = value || '';
},
getItem: function(key) {
return key in storage ? storage[key] : null;
},
removeItem: function(key) {
delete storage[key];
},
get length() {
return Object.keys(storage).length;
},
key: function(i) {
var keys = Object.keys(storage);
return keys[i] || null;
}
};
}
Run Code Online (Sandbox Code Playgroud)
然后你实际做的是这样的:
// mock the localStorage
window.localStorage = storageMock();
// mock the sessionStorage
window.sessionStorage = storageMock();
Run Code Online (Sandbox Code Playgroud)
Cla*_*ijo 19
还要考虑在对象的构造函数中注入依赖项的选项.
var SomeObject(storage) {
this.storge = storage || window.localStorage;
// ...
}
SomeObject.prototype.doSomeStorageRelatedStuff = function() {
var myValue = this.storage.getItem('myKey');
// ...
}
// In src
var myObj = new SomeObject();
// In test
var myObj = new SomeObject(mockStorage)
Run Code Online (Sandbox Code Playgroud)
与模拟和单元测试一致,我喜欢避免测试存储实现.例如,在设置项目等之后检查存储长度是否增加没有意义.
因为替换真正的localStorage对象上的方法显然是不可靠的,所以使用"哑"mockStorage并根据需要存根各个方法,例如:
var mockStorage = {
setItem: function() {},
removeItem: function() {},
key: function() {},
getItem: function() {},
removeItem: function() {},
length: 0
};
// Then in test that needs to know if and how setItem was called
sinon.stub(mockStorage, 'setItem');
var myObj = new SomeObject(mockStorage);
myObj.doSomeStorageRelatedStuff();
expect(mockStorage.setItem).toHaveBeenCalledWith('myKey');
Run Code Online (Sandbox Code Playgroud)
Cha*_*rdy 11
这就是我做的......
var mock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key];
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', {
value: mock,
});
Run Code Online (Sandbox Code Playgroud)
当前的解决方案无法在Firefox中使用。这是因为html规范将localStorage定义为不可修改。但是,您可以通过直接访问localStorage的原型来解决此问题。
跨浏览器解决方案是模拟对象,Storage.prototype
例如
代替spyOn(localStorage,'setItem')使用
spyOn(Storage.prototype, 'setItem')
spyOn(Storage.prototype, 'getItem')
Run Code Online (Sandbox Code Playgroud)
摘自bzbarsky和 teogeos在这里的回复https://github.com/jasmine/jasmine/issues/299
那里有没有图书馆要模拟
localStorage
?
我刚写了一篇:
(function () {
var localStorage = {};
localStorage.setItem = function (key, val) {
this[key] = val + '';
}
localStorage.getItem = function (key) {
return this[key];
}
Object.defineProperty(localStorage, 'length', {
get: function () { return Object.keys(this).length - 2; }
});
// Your tests here
})();
Run Code Online (Sandbox Code Playgroud)
我的初步测试显示localStorage拒绝在firefox中分配
仅在全球范围内.使用上面的包装函数,它工作得很好.
小智 5
根据某些答案中的建议覆盖localStorage
全局window
对象的属性在大多数 JS 引擎中不起作用,因为它们将localStorage
data 属性声明为不可写且不可配置。
但是我发现至少在 PhantomJS(版本 1.9.8)WebKit 版本中,您可以使用旧版 API__defineGetter__
来控制localStorage
访问时会发生什么。如果这也适用于其他浏览器,那将会很有趣。
var tmpStorage = window.localStorage;
// replace local storage
window.__defineGetter__('localStorage', function () {
throw new Error("localStorage not available");
// you could also return some other object here as a mock
});
// do your tests here
// restore old getter to actual local storage
window.__defineGetter__('localStorage',
function () { return tmpStorage });
Run Code Online (Sandbox Code Playgroud)
这种方法的好处是您不必修改要测试的代码。
您不必将存储对象传递给使用它的每个方法。相反,您可以为接触存储适配器的任何模块使用配置参数。
你的旧模块
// hard to test !
export const someFunction (x) {
window.localStorage.setItem('foo', x)
}
// hard to test !
export const anotherFunction () {
return window.localStorage.getItem('foo')
}
Run Code Online (Sandbox Code Playgroud)
具有配置“包装器”功能的新模块
export default function (storage) {
return {
someFunction (x) {
storage.setItem('foo', x)
}
anotherFunction () {
storage.getItem('foo')
}
}
}
Run Code Online (Sandbox Code Playgroud)
当您在测试代码中使用该模块时
// import mock storage adapater
const MockStorage = require('./mock-storage')
// create a new mock storage instance
const mock = new MockStorage()
// pass mock storage instance as configuration argument to your module
const myModule = require('./my-module')(mock)
// reset before each test
beforeEach(function() {
mock.clear()
})
// your tests
it('should set foo', function() {
myModule.someFunction('bar')
assert.equal(mock.getItem('foo'), 'bar')
})
it('should get foo', function() {
mock.setItem('foo', 'bar')
assert.equal(myModule.anotherFunction(), 'bar')
})
Run Code Online (Sandbox Code Playgroud)
这个MockStorage
类可能看起来像这样
export default class MockStorage {
constructor () {
this.storage = new Map()
}
setItem (key, value) {
this.storage.set(key, value)
}
getItem (key) {
return this.storage.get(key)
}
removeItem (key) {
this.storage.delete(key)
}
clear () {
this.constructor()
}
}
Run Code Online (Sandbox Code Playgroud)
在生产代码中使用你的模块时,改为传递真正的 localStorage 适配器
const myModule = require('./my-module')(window.localStorage)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
64893 次 |
最近记录: |