当我尝试测试使用 jasmine promise 的 Controller 时,我遇到了一些问题。
我有以下 Jasmine 测试:
describe('Testing a controller', function () {
var $scope, $root, ctrl, $q, deferred;
var MockService;
beforeEach(function () {
module('myApp');
inject(function ($rootScope, $controller, $q) {
$root = $rootScope;
$scope = $rootScope.$new();
MockService = {
fetch: function () {
return {
get: function () {
deferred = $q.defer();
return {
$promise: deferred.promise
};
}
};
}
};
ctrl = $controller('myController', {
$scope: $scope,
$root: $rootScope,
MyService: MockService,
});
});
spyOn(MockService, 'fetch').andCallThrough();
});
it('Get data from promise', function () {
$scope.init();
deferred.resolve("It worked!");
$root.$digest();
expect(MockService.fetch).toHaveBeenCalled();
expect($scope.test).toBe('It worked!');
});
});
这是 Controller :
controllers.controller('myController', ['$scope','MyService'
function ($scope, myService) {
$scope.init = function () {
myService.fetch().get().$promise.then(function (data) {
$scope.test = data;
}, function (error) {
$scope.error = error;
});
};
}
]);
测试一直失败:“预期未定义为‘It Worked!’。”
看起来 promise 得到了解决,并且“then”函数从未被调用。有什么想法吗?
最佳答案
您上面提供的代码似乎可以工作(现在 @dfsq 的修复已应用)。
我只能通过注释掉以下任一行来重现您遇到的错误:
deferred.resolve("It worked!");
$root.$digest();
...这让我想知道在您的实际代码(不是上面提供的示例)中,上述两行代码的等效项的实现是否存在问题。
您是否曾在同一测试的早期阶段执行过 deferred.reject()
或 deferred.resolve()
而不传递参数?
使用 HTMLReporter 进行 jasmine 测试的演示:
/* Angular App */
(function() {
"use strict";
angular.module('myApp', [])
.controller('myController', ['$scope', 'MyService',
function($scope, myService) {
$scope.init = function() {
myService.fetch().get().$promise.then(function(data) {
$scope.test = data;
}, function(error) {
$scope.error = error;
});
};
}
]);
})();
/* Unit Test */
(function() {
"use strict";
var consoleLog = document.querySelector('#log');
describe('Testing a controller', function() {
var $scope, $root, ctrl, $q, deferred;
var MockService;
beforeEach(function() {
module('myApp');
inject(function($rootScope, $controller, $q) {
$root = $rootScope;
$scope = $rootScope.$new();
MockService = {
fetch: function() {
return {
get: function() {
deferred = $q.defer();
return {
$promise: deferred.promise
};
}
};
}
};
ctrl = $controller('myController', {
$scope: $scope,
$root: $rootScope,
MyService: MockService,
});
});
spyOn(MockService, 'fetch').andCallThrough();
});
it('Get data from promise', function() {
consoleLog.innerHTML += "<p>" + [
"START OF TEST:",
"$scope.test: " + $scope.test,
"$scope.error: " + $scope.error
].join("<br />") + "</p>";
$scope.init();
deferred.resolve("It worked!");
$root.$digest();
expect(MockService.fetch).toHaveBeenCalled();
expect($scope.test).toBe('It worked!');
consoleLog.innerHTML += "<p>" + [
"END OF TEST:",
"$scope.test: " + $scope.test,
"$scope.error: " + $scope.error
].join("<br />") + "</p>";
});
});
})();
/* Jasmine Bootstrap */
(function() {
"use strict";
var jasmineEnv = jasmine.getEnv(),
htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.execute();
})();
<link rel="stylesheet" href="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" />
<script src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
<script src="//cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular-mocks.js"></script>
<pre id="log"></pre>
关于AngularJS promise 在使用 Jasmine 进行测试时不会调用 then,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32114595/