我试图嘲笑有角度的承诺,但是我得到了一些错误,比如undefined不是一个评估&spudOn' fileUploadService
我的控制器代码是
$scope.getUserFiles = function() {
fileUploadService.retrieveUserFileNames('')
.then(function(data) {
$scope.userFiles = data;
});
};
服务代码,我从我的控制器中调用此方法
this.retrieveUserFileNames= function(userId) {
var deferred = $q.defer();
$http({
method : "GET",
url : "/retrieveExcelSheetNames",
params : {
"userId" : userId
}
}).success(function(data) {
deferred.resolve(data);
}).error(function(data, status) {
deferred.reject(data);
});
return deferred.promise;
};
测试控制器代码
beforeEach(function() {
inject(function(_fileUploadService_ , _$q_) {
spyOn(scope, '$on');
var deferred = _$q_.defer();
fileUploadService = _fileUploadService_;
deferred.resolve('resolveData');
spyOn(fileUploadService, 'retrieveUserFileNames').andReturn(deferred.promise);
});
});
it('is now a lot easier', function() {
scope.getUserFiles();
rootScope.$apply();
expect(scope.userFiles).toBe('resolveData');
});
由于
答案 0 :(得分:2)
当您在控制器中异步设置$scope.userFiles
时,您需要等待$apply
$http
解决您的承诺。
假设您正在使用Jasmine,您可以使用异步规范表示法并注册$watch
函数来测试您的控制器(没有测试代码,因此您可能需要对其进行调整,这也取决于其他修改范围变量)。
it('is now a lot easier', function(done) {
scope.$watch('userFiles', function() {
expect(scope.userFiles).toBe('resolveData');
// Call done function to tell Jasmine that the spec has completed
done();
});
scope.getUserFiles();
});
但是,我认为您应该测试您的服务,并且可以使用覆盖$ http的$httpBackend from ngMock并使您能够进行更深入的测试。在那里,您可以测试/监视对模拟后端的调用,并使用Jasmines done()
函数来等待承诺。
这是一个简单的例子:
angular.module('mainApp', [])
// Simple factory that uses $http for later use of $httpBackend mocking structure
.factory('userManager', function($http, $q) {
return $http.get('/api/users');
});
规格:
describe('Simple factory that uses $http for later use of $httpBackend mocking structure', function() {
// We need to use the module mainApp for all our tests
beforeEach(module('mainApp'));
// We use $httpBackend from ngMock module to mock our webservice call ($http will be overriden)
// Also we need to inject inside of spec function as we need to use the async spec form with
// a done function and this is not available using the inject to proxy the spec function
it('should return desired user list', function(done) {
inject(function($httpBackend, userManager) {
$httpBackend.when('GET', '/api/users').respond({
userList: [
{user: 'User A'},
{user: 'User B'},
{user: 'User C'},
{user: 'User D'},
]
});
$httpBackend.expectGET('/api/users');
// userManager is returning a promise so we need to check asynchronously
userManager.getUserList().then(function(result) {
expect(result.data.userList).toContain(
{user: 'User A'},
{user: 'User B'},
{user: 'User C'},
{user: 'User D'}
);
// This call to the Jasmine done function is very important for asynchronous
// unit tests as Jasmine is determining if the test is done by this call
done();
});
$httpBackend.flush();
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
});
});