How do I unit-test a factory that uses $window.localStorage
internally using Jasmine and ngMock?
Here's something similar to what I have:
myApp.factory('myData',function ($window) {
return {
message: $window.localStorage['stuff']
}
});
Thanks a bunch!
The following works with Jasmine 2.4:
angular.module('MyModule', []).factory('myData',function ($window) {
return {
message: function(){
return $window.localStorage['stuff'] ;
}
}
});
describe("TestName", function() {
beforeEach(module('MyModule'));
var myData, store;
beforeEach(inject(function(_myData_) {
myData = _myData_;
store = {};
var localStorage = window.localStorage;
spyOn(localStorage, 'getItem').and.callFake(function (key) {
return store[key];
});
spyOn(localStorage, 'setItem').and.callFake(function (key, value) {
return store[key] = value + '';
});
spyOn(localStorage, 'clear').and.callFake(function () {
store = {};
});
}));
it("feature desc", function() {
localStorage['stuff'] = 'hello';
expect(myData.message()).toEqual('hello');
});
});
Note use of the _myData_ underscore trick (see docs).
Small clarification: in case localStorage doesn't contain a key this mock return undefined
, but real one returns null
The getItem(key) method must return the current value associated with the given key. If the given key does not exist in the list associated with the object then this method must return null. https://www.w3.org/TR/webstorage/
spyOn(localStorage, 'getItem').and.callFake(function (key) {
return store[key] !== undefined ? store[key] : null;
});
Note: in the previous example method removeItem
was not mocked
spyOn(localStorage, 'removeItem').and.callFake(function (key, value) {
delete store[key];
});
P.S. I've found another way to write tests with local storage without mock it, probably it makes sense, working with primitives and localStorage could be tricky.
afterEach(() => {
localStorage.removeItem(testTokenKey);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With