Jasmine 和 angular 模拟:模拟处理本地存储的服务
Jasmine and angular mocks : mocking a service that handles local storage
我有一项名为 wd$cache 的服务,它基本上是 localStorage.setItem 和 get.item 的包装器。
现在我正在尝试测试使用该服务实现特定结果的控制器。主要问题是我有一个 IF 语句,只有当你已经设置了 localstorage 时才会触发它,这让我抓狂! (我们这里做的是TDD)
服务
(function () {
angular
.module('hub')
.controller('promotionNotificationCtrl', promotionNotificationCtrl);
promotionNotificationCtrl.$inject = [
'hub$promotions',
'hub$client',
'wd$cache'
];
function promotionNotificationCtrl(
hub$promotions,
hub$client,
wd$cache) {
var vm = this;
activate();
//////////
function activate () {
hub$promotions.get(hub$client.brand, hub$client.subbrand).success(function (data) {
if (!wd$cache.get('hub$notification')) {
wd$cache.add('before', 123);
} else {
wd$cache.add('after', 321);
}
});
}
}
})();
测试
describe('The promotion notification controller', function () {
var controller,
hub$client,
$httpBackend,
wd$cache,
mockData = [{
"foo": "bar"
},
{
"faa": "boo"
}];
beforeEach(module('hub'));
beforeEach(module('wired.core'));
beforeEach(module(function ($provide) {
hub$client = {
brand: 'bw',
subbrand: 'plus'
};
wd$cache = {
add: function () {
},
get: function () {
}
};
$provide.value('hub$client', hub$client);
$provide.value('wd$cache', wd$cache);
spyOn(wd$cache, 'add');
}));
beforeEach(inject(function ($controller, _$httpBackend_, _hub$promotions_) {
controller = $controller('promotionNotificationCtrl');
$httpBackend = _$httpBackend_;
hub$promotions = _hub$promotions_;
// request
$httpBackend.expectGET("/umbraco/api/promotions/get/?brand=bw&lang=en&subbrand=plus").respond(200, mockData);
$httpBackend.flush();
}));
it('should attempt to add a cache with a "before" key if no previous "hub$notification" cache was found', function () {
expect(wd$cache.add).toHaveBeenCalledWith('before', 123); //WORKING
})
it('should attempt to add a cache with a "after" key if a previous "hub$notification" cache was found', function () {
localStorage.setItem('hub$notification');
wd$cache.add('hub$notification');
expect(wd$cache.add).toHaveBeenCalledWith('after', 123); // NOT WORKING
// CANT GET THROUGH THE IF STATEMENT
})
});
基本上,无论我做什么,我都无法在 BeforeEach 块之后到达 'Test Cases'。自从模拟它以使用实际存储以来,我已经尝试了一切。
有什么想法吗?
您可以提供一个已经填充了一些数据的模拟实现:
var cache = {};
beforeEach(module(function ($provide) {
// ...
wd$cache = {
add: function (key, value) {
cache[key] = value;
},
get: function (key) {
return cache[key];
}
};
// add initial data here or in the individual tests, e.g.
// ...
}));
要为特定测试用例正确设置缓存,您可以像这样使用 cache
字段:
cache['hub$notification'] = 'whatever value makes sense here';
当然你也可以在beforeEach
中这样做。
目前您正在尝试这样做:
wd$cache.add('hub$notification');
expect(wd$cache.add).toHaveBeenCalledWith('after', 123);
这是有问题的,原因有二:
您没有更新缓存,因为您在没有 .andCallThrough()
的情况下监视 add
方法。您应该修复此问题(在创建间谍后添加 .andCallThrough()
),否则来自控制器的更新将不会影响缓存。
间谍会记录您的通话。您不希望将此用于设置代码,因为它会使后续断言更加复杂。
我有一项名为 wd$cache 的服务,它基本上是 localStorage.setItem 和 get.item 的包装器。
现在我正在尝试测试使用该服务实现特定结果的控制器。主要问题是我有一个 IF 语句,只有当你已经设置了 localstorage 时才会触发它,这让我抓狂! (我们这里做的是TDD)
服务
(function () {
angular
.module('hub')
.controller('promotionNotificationCtrl', promotionNotificationCtrl);
promotionNotificationCtrl.$inject = [
'hub$promotions',
'hub$client',
'wd$cache'
];
function promotionNotificationCtrl(
hub$promotions,
hub$client,
wd$cache) {
var vm = this;
activate();
//////////
function activate () {
hub$promotions.get(hub$client.brand, hub$client.subbrand).success(function (data) {
if (!wd$cache.get('hub$notification')) {
wd$cache.add('before', 123);
} else {
wd$cache.add('after', 321);
}
});
}
}
})();
测试
describe('The promotion notification controller', function () {
var controller,
hub$client,
$httpBackend,
wd$cache,
mockData = [{
"foo": "bar"
},
{
"faa": "boo"
}];
beforeEach(module('hub'));
beforeEach(module('wired.core'));
beforeEach(module(function ($provide) {
hub$client = {
brand: 'bw',
subbrand: 'plus'
};
wd$cache = {
add: function () {
},
get: function () {
}
};
$provide.value('hub$client', hub$client);
$provide.value('wd$cache', wd$cache);
spyOn(wd$cache, 'add');
}));
beforeEach(inject(function ($controller, _$httpBackend_, _hub$promotions_) {
controller = $controller('promotionNotificationCtrl');
$httpBackend = _$httpBackend_;
hub$promotions = _hub$promotions_;
// request
$httpBackend.expectGET("/umbraco/api/promotions/get/?brand=bw&lang=en&subbrand=plus").respond(200, mockData);
$httpBackend.flush();
}));
it('should attempt to add a cache with a "before" key if no previous "hub$notification" cache was found', function () {
expect(wd$cache.add).toHaveBeenCalledWith('before', 123); //WORKING
})
it('should attempt to add a cache with a "after" key if a previous "hub$notification" cache was found', function () {
localStorage.setItem('hub$notification');
wd$cache.add('hub$notification');
expect(wd$cache.add).toHaveBeenCalledWith('after', 123); // NOT WORKING
// CANT GET THROUGH THE IF STATEMENT
})
});
基本上,无论我做什么,我都无法在 BeforeEach 块之后到达 'Test Cases'。自从模拟它以使用实际存储以来,我已经尝试了一切。
有什么想法吗?
您可以提供一个已经填充了一些数据的模拟实现:
var cache = {};
beforeEach(module(function ($provide) {
// ...
wd$cache = {
add: function (key, value) {
cache[key] = value;
},
get: function (key) {
return cache[key];
}
};
// add initial data here or in the individual tests, e.g.
// ...
}));
要为特定测试用例正确设置缓存,您可以像这样使用 cache
字段:
cache['hub$notification'] = 'whatever value makes sense here';
当然你也可以在beforeEach
中这样做。
目前您正在尝试这样做:
wd$cache.add('hub$notification');
expect(wd$cache.add).toHaveBeenCalledWith('after', 123);
这是有问题的,原因有二:
您没有更新缓存,因为您在没有
.andCallThrough()
的情况下监视add
方法。您应该修复此问题(在创建间谍后添加.andCallThrough()
),否则来自控制器的更新将不会影响缓存。间谍会记录您的通话。您不希望将此用于设置代码,因为它会使后续断言更加复杂。