在 Karma 中测试 Angular 服务:同样的测试,不同的结果
Testing Angular Service in Karma: Same Test, Different Results
我正在尝试使用 Karma 测试一个 Angular 服务,得到了一些奇怪的结果,所以为了好玩,我做了两个相同的测试,看看我是否会得到相同的结果,但是我没有:
describe('Profile Data Service', function() {
var LoginData, rootScope, $httpBackend;
beforeEach(module('myApp'));
describe('get profile data', function() {
beforeEach(inject(function(_LoginData_, $rootScope, _$httpBackend_) {
LoginData = _LoginData_;
LoginData.username= "jsmith";
LoginData.token = "token";
rootScope = $rootScope;
$httpBackend = _$httpBackend_;
}));
it('should get profile data on instantiation', inject(function(ProfileDataService) {
$httpBackend.expect('POST', 'http://mytestserver.com/api/', {
params: [{
username: "jsmith",
token: "token",
method: "getProfile"
}]
})
.respond({
result: {
address: "111 Main St."
city: "Los Angeles",
state: "CA"
}
});
$httpBackend.flush();
expect(ProfileDataService.profileData.address).toMatch("111 Main St.");
}));
it('should get profile data on instantiation', inject(function(ProfileDataService) {
$httpBackend.expect('POST', 'http://mytestserver.com/api/', {
params: [{
username: "jsmith",
token: "token",
method: "getProfile"
}]
})
.respond({
result: {
address: "111 Main St."
city: "Los Angeles",
state: "CA"
}
});
$httpBackend.flush();
expect(ProfileDataService.profileData.address).toMatch("111 Main St.");
}));
});
});
第一个测试通过,但第二个测试指出 profileData 未定义。它们是相同的测试。我假设每个 it
ProfileDataService 都被重新初始化,但事实可能并非如此。如果那不是真的,我如何创建单独的测试以便我的服务被销毁并为每个测试用例重新初始化?
该服务的逻辑相当简单:
(function() {
'use strict';
angular.module('servicesModule')
.service('ProfileDataService', ProfileDataService);
ProfileDataService.$inject = ["$http", "$q", "LoginData", "CacheFactory"];
function ProfileDataService($http, $q, LoginData, CacheFactory) {
var ProfileDataService = this;
(function() {
init();
})();
function init() {
getProfile().then(function(profileData) {
ProileDataService.profileData = profileData;
});
}
function getProfile() {
var deferred = $q.defer();
var data = {
params: [{
username: LoginData.username,
token: LoginData.token,
method: "getProfile"
}]
};
var profileDataCache = CacheFactory.get('profileDataCache');
if (profileDataCache.get('profileData') && !invalidateCache) {
deferred.resolve(profileDataCache.get('profileData'));
}
else {
$http.post('http://mytestserver.com/api/', data)
.success(function(data) {
profileDataCache.put('profileData', response.result);
deferred.resolve(data.result);
});
}
return deferred.promise;
}
}
})();
我还应该注意,我已经尝试在测试的不同位置添加 rootScope.$digest()
,但这似乎没有任何区别。我认为手动触发摘要循环将确保捕获 http post 并模拟响应。
编辑:我漏掉了一个很大的细节...angular-cache
。我忘了提到我正在使用缓存插件。这就是我的问题的原因。在创建一个 plunker 并看到我为相同的测试获得了一致的结果后,我知道有些事情我没有意识到。由于我的缓存逻辑,第二个测试没有发出 POST 请求。
我的问题是没有意识到我对缓存的使用为我的每次测试提供了不同的结果。具体来说,如果已经为该响应保留缓存,我的服务逻辑会阻止 POST 到 api。
我正在尝试使用 Karma 测试一个 Angular 服务,得到了一些奇怪的结果,所以为了好玩,我做了两个相同的测试,看看我是否会得到相同的结果,但是我没有:
describe('Profile Data Service', function() {
var LoginData, rootScope, $httpBackend;
beforeEach(module('myApp'));
describe('get profile data', function() {
beforeEach(inject(function(_LoginData_, $rootScope, _$httpBackend_) {
LoginData = _LoginData_;
LoginData.username= "jsmith";
LoginData.token = "token";
rootScope = $rootScope;
$httpBackend = _$httpBackend_;
}));
it('should get profile data on instantiation', inject(function(ProfileDataService) {
$httpBackend.expect('POST', 'http://mytestserver.com/api/', {
params: [{
username: "jsmith",
token: "token",
method: "getProfile"
}]
})
.respond({
result: {
address: "111 Main St."
city: "Los Angeles",
state: "CA"
}
});
$httpBackend.flush();
expect(ProfileDataService.profileData.address).toMatch("111 Main St.");
}));
it('should get profile data on instantiation', inject(function(ProfileDataService) {
$httpBackend.expect('POST', 'http://mytestserver.com/api/', {
params: [{
username: "jsmith",
token: "token",
method: "getProfile"
}]
})
.respond({
result: {
address: "111 Main St."
city: "Los Angeles",
state: "CA"
}
});
$httpBackend.flush();
expect(ProfileDataService.profileData.address).toMatch("111 Main St.");
}));
});
});
第一个测试通过,但第二个测试指出 profileData 未定义。它们是相同的测试。我假设每个 it
ProfileDataService 都被重新初始化,但事实可能并非如此。如果那不是真的,我如何创建单独的测试以便我的服务被销毁并为每个测试用例重新初始化?
该服务的逻辑相当简单:
(function() {
'use strict';
angular.module('servicesModule')
.service('ProfileDataService', ProfileDataService);
ProfileDataService.$inject = ["$http", "$q", "LoginData", "CacheFactory"];
function ProfileDataService($http, $q, LoginData, CacheFactory) {
var ProfileDataService = this;
(function() {
init();
})();
function init() {
getProfile().then(function(profileData) {
ProileDataService.profileData = profileData;
});
}
function getProfile() {
var deferred = $q.defer();
var data = {
params: [{
username: LoginData.username,
token: LoginData.token,
method: "getProfile"
}]
};
var profileDataCache = CacheFactory.get('profileDataCache');
if (profileDataCache.get('profileData') && !invalidateCache) {
deferred.resolve(profileDataCache.get('profileData'));
}
else {
$http.post('http://mytestserver.com/api/', data)
.success(function(data) {
profileDataCache.put('profileData', response.result);
deferred.resolve(data.result);
});
}
return deferred.promise;
}
}
})();
我还应该注意,我已经尝试在测试的不同位置添加 rootScope.$digest()
,但这似乎没有任何区别。我认为手动触发摘要循环将确保捕获 http post 并模拟响应。
编辑:我漏掉了一个很大的细节...angular-cache
。我忘了提到我正在使用缓存插件。这就是我的问题的原因。在创建一个 plunker 并看到我为相同的测试获得了一致的结果后,我知道有些事情我没有意识到。由于我的缓存逻辑,第二个测试没有发出 POST 请求。
我的问题是没有意识到我对缓存的使用为我的每次测试提供了不同的结果。具体来说,如果已经为该响应保留缓存,我的服务逻辑会阻止 POST 到 api。