显示模块模式和变量范围 -> public 对象在异步调用后未定义 returns
revealing module pattern & variable scope -> public object undefined after async call returns
我有一个 Angular 控制器,它似乎工作正常。我可以在服务调用中控制台记录用户变量,它包含正确的数据。但是在我的测试中,我可以控制台登录控制器并验证用户对象是否存在,但它是空的。看起来 initialize 确实试图在局部作用域被销毁后存储变量,但这很奇怪,因为我有另一个控制器和以完全相同的方式编写的测试工作正常。
这两天我一直在反复研究这个问题,所以如果有人有任何线索,我将不胜感激。
function DetailAccountController (accountsService) {
'use strict';
var user = {};
initialize();
return {
user: user
};
/**
* Initialize the controller,
* & fetch detail for a single user.
*/
function initialize () {
// If the service is available, then fetch the user
accountsService && accountsService.getById('').then(function (res) {
user = res;
});
}
}
和茉莉花测试:
describe('DetailAccountController', function () {
var ctrl = require('./detail-account-controller'),
data = [{
"email": "fakeUser0@gmail.com",
"voornaam": "Mr Fake0",
"tussenvoegsel": "van0",
"achternaam": "User0",
"straat": "Mt Lincolnweg0",
"huisnr": 0,
"huisnr_toev": 0,
"postcode": "0LW",
"telefoonr": "0200000000",
"mobielnr": "0680000000",
"plaats": "Amsterdam",
"id": "00000000"
}],
accountsServiceMock,
$rootScope,
$q;
beforeEach(inject(function (_$q_, _$rootScope_) {
$q = _$q_;
$rootScope = _$rootScope_;
accountsServiceMock = {
getById: function () {}
};
}));
it('should call the getById method at least once', function () {
spyOn(accountsServiceMock, 'getById').and.returnValue($q.defer().promise);
ctrl.call({}, accountsServiceMock);
expect(accountsServiceMock.getById.calls.any()).toBe(true);
expect(accountsServiceMock.getById.calls.count()).toBe(1);
});
it('should populate user data in the model', function () {
var deferred = $q.defer();
deferred.resolve(data);
spyOn(accountsServiceMock, 'getById').and.returnValue(deferred.promise);
var vm = ctrl.call({}, accountsServiceMock);
$rootScope.$apply();
expect(vm.user).toEqual(data);
});
});
针对好奇的更新解决方案
function DetailAccountController (accountsService) {
'use strict';
var self = this;
self.user = null;
initialize();
return self;
/**
* Initialize the controller,
* & fetch detail for a single user.
*/
function initialize () {
accountsService && accountsService.getById('').then(function (res) {
self.user = res;
});
}
}
user = res
影响局部变量,与返回对象无关。
必须是
accountsService && accountsService.getById('').then(function (res) {
angular.extend(user, res);
});
或
var obj = {
user: {}
};
initialize();
return obj;
function initialize () {
accountsService && accountsService.getById('').then(function (res) {
obj.user = res;
});
}
我有一个 Angular 控制器,它似乎工作正常。我可以在服务调用中控制台记录用户变量,它包含正确的数据。但是在我的测试中,我可以控制台登录控制器并验证用户对象是否存在,但它是空的。看起来 initialize 确实试图在局部作用域被销毁后存储变量,但这很奇怪,因为我有另一个控制器和以完全相同的方式编写的测试工作正常。
这两天我一直在反复研究这个问题,所以如果有人有任何线索,我将不胜感激。
function DetailAccountController (accountsService) {
'use strict';
var user = {};
initialize();
return {
user: user
};
/**
* Initialize the controller,
* & fetch detail for a single user.
*/
function initialize () {
// If the service is available, then fetch the user
accountsService && accountsService.getById('').then(function (res) {
user = res;
});
}
}
和茉莉花测试:
describe('DetailAccountController', function () {
var ctrl = require('./detail-account-controller'),
data = [{
"email": "fakeUser0@gmail.com",
"voornaam": "Mr Fake0",
"tussenvoegsel": "van0",
"achternaam": "User0",
"straat": "Mt Lincolnweg0",
"huisnr": 0,
"huisnr_toev": 0,
"postcode": "0LW",
"telefoonr": "0200000000",
"mobielnr": "0680000000",
"plaats": "Amsterdam",
"id": "00000000"
}],
accountsServiceMock,
$rootScope,
$q;
beforeEach(inject(function (_$q_, _$rootScope_) {
$q = _$q_;
$rootScope = _$rootScope_;
accountsServiceMock = {
getById: function () {}
};
}));
it('should call the getById method at least once', function () {
spyOn(accountsServiceMock, 'getById').and.returnValue($q.defer().promise);
ctrl.call({}, accountsServiceMock);
expect(accountsServiceMock.getById.calls.any()).toBe(true);
expect(accountsServiceMock.getById.calls.count()).toBe(1);
});
it('should populate user data in the model', function () {
var deferred = $q.defer();
deferred.resolve(data);
spyOn(accountsServiceMock, 'getById').and.returnValue(deferred.promise);
var vm = ctrl.call({}, accountsServiceMock);
$rootScope.$apply();
expect(vm.user).toEqual(data);
});
});
针对好奇的更新解决方案
function DetailAccountController (accountsService) {
'use strict';
var self = this;
self.user = null;
initialize();
return self;
/**
* Initialize the controller,
* & fetch detail for a single user.
*/
function initialize () {
accountsService && accountsService.getById('').then(function (res) {
self.user = res;
});
}
}
user = res
影响局部变量,与返回对象无关。
必须是
accountsService && accountsService.getById('').then(function (res) {
angular.extend(user, res);
});
或
var obj = {
user: {}
};
initialize();
return obj;
function initialize () {
accountsService && accountsService.getById('').then(function (res) {
obj.user = res;
});
}