[英]Unit testing for function
I'm writing a unit test for function getNextPage(). 我正在为功能getNextPage()编写单元测试。 I set the test: expect(this.anotherService.resources).toEqual(3);
我设置了测试:Expect(this.anotherService.resources).toEqual(3); I got error: Expected undefined to equal 3 when running the test.
我收到错误消息:运行测试时,预期undefined等于3。 I logged the anotherService.resources and it returned 3 in console.
我记录了anotherService.resources,它在控制台中返回了3。 Not sure why it's not working.
不知道为什么它不起作用。
Test 测试
describe('Test for someController', function() {
beforeEach(function() {
module('someApp');
return inject(function($injector) {
var $controller;
var $q = $injector.get('$q');
this.rootScope = $injector.get('$rootScope');
$controller = $injector.get('$controller');
this.state = $injector.get('$state');
this.stateParams = {
id: 1,
}
this.location = $injector.get('$location')
this.timeout = $injector.get('$timeout')
this.upload = $injector.get('$upload')
this.someService = {
getItemList: function(res) {
var deferred = $q.defer();
deferred.resolve({
data: {
totalRows: 2,
rows: 3,
}
});
return deferred.promise;
},
pages: jasmine.createSpy(),
memberIds: 1,
currEng: []
};
this.anotherService = {
resources: {}
};
this.scope = this.rootScope.$new();
this.controller = $controller('someController', {
'$scope': this.scope,
'$rootScope': this.rootScope,
'$state': this.state,
'$stateParams': this.stateParams,
'$location': this.location,
'$timeout': this.timeout,
'$upload': this.upload,
'someService': this.someService,
});
this.scope.$digest();
});
});
it('should be defined', function() {
expect(this.controller).toBeDefined();
expect(this.scope.ss).toEqual(this.someService);
});
it('should run the getNextPage function', function() {
this.scope.getNextPage();
this.scope.$digest();
console.log(this.anotherService.resources); // this is showing as Object {} in terminal
expect(this.anotherService.resources).toEqual(3);
});
Code: 码:
someapp.controller('someController', resource);
resource.$inject = ['$scope', '$state', '$stateParams', '$location','$timeout','$upload', 'someService', 'anotherService'];
function resource($scope, $state, $stateParams,$location,$timeout, $upload, someService, anotherService) {
$scope.fileReaderSupported = window.FileReader != null && (window.FileAPI == null || FileAPI.html5 != false);
$scope.ss = EsomeService;
$scope.as = anotherService;
$scope.getNextPage = getNextPage;
function getNextPage(options){
var o = options || {selected:1};
var start = (o.selected-1)*10 || 0;
someService.currPage = o.selected;
someService.getItemList($stateParams.id,'F', start).then(function (res){
anotherService.resources = res.data.rows;
console.log(anotherService.resources) // this shows LOG: 3 in terminal
someService.numResults = res.data.totalRows;
someService.pageNumbers = someService.pages(res.data.totalRows,10);
})
}
});
The value of this.anotherService.resources
is still {}
in your test because the code in the following then
callback is executed after your test runs, asynchronously: 在您的测试中,
this.anotherService.resources
的值仍为{}
,因为在测试运行之后 ,以下then
回调中的代码是异步运行的:
someService.getItemList($stateParams.id,'F', start).then(function (res){
anotherService.resources = res.data.rows;
console.log(anotherService.resources)
someService.numResults = res.data.totalRows;
someService.pageNumbers = someService.pages(res.data.totalRows,10);
})
Although in getItemList
you resolve the promise synchronously 尽管在
getItemList
您可以同步解决promise
getItemList: function(res) {
var deferred = $q.defer();
deferred.resolve({
data: {
totalRows: 2,
rows: 3,
}
});
return deferred.promise;
},
... it actually does not call the then
function on the promise immediately when you call deferred.resolve
. ...实际上,当您调用
deferred.resolve
时,它不会立即在promise上调用then
函数。 When you think of it, that would not make sense either, because the promise must first be returned to the caller before the caller can attach the then
call back to it. 当您想到它时,也没有任何意义,因为必须先将诺言返回给呼叫者,然后呼叫者才能附加“
then
再回叫给它。 Instead it calls the then
callback asynchronously, ie after all currently executing code finishes with an empty call stack. 相反,它异步地调用
then
回调,即在所有当前执行的代码完成后都带有一个空的调用栈。 This includes your test code! 这包括您的测试代码! As stated in the Angular documentation :
如Angular文档中所述 :
then(successCallback, errorCallback, notifyCallback)
– regardless of when the promise was or will be resolved or rejected,then
calls one of the success or error callbacks asynchronously as soon as the result is available.then(successCallback, errorCallback, notifyCallback)
–无论何时或将要解决或拒绝promise,then
在结果可用时立即异步调用成功或错误回调之一。
and also in the testing example in the same documentation : 以及同一文档中的测试示例 :
// Simulate resolving of promise deferred.resolve(123); // Note that the 'then' function does not get called synchronously. // This is because we want the promise API to always be async, whether or not // it got called synchronously or asynchronously.
First, you could let getNextPage
return a promise -- the same promise that getItemList
returns: 首先,您可以让
getNextPage
返回一个诺言-与getItemList
返回的诺言相同:
function getNextPage(options){
var o = options || {selected:1};
var start = (o.selected-1)*10 || 0;
someService.currPage = o.selected;
// store the promise in a variable
var prom = someService.getItemList($stateParams.id,'F', start);
prom.then(function (res){
anotherService.resources = res.data.rows;
console.log(anotherService.resources) // this shows LOG: 3 in terminal
someService.numResults = res.data.totalRows;
someService.pageNumbers = someService.pages(res.data.totalRows,10);
});
return prom; // return that promise
}
And then you can use then
on getNextPage()
, which will execute in sequence with any other then
callbacks attached to it, so after the then
callback in the above piece of code. 然后,您可以在
getNextPage()
上使用then
,它将与附加的其他then
回调依次执行,因此在上述代码的then
回调之后。
Jasmine's done
can then be used to tell Jasmine the test is asynchronous and when it has completed: 然后可以使用Jasmine的
done
来告诉Jasmine测试是异步的,以及何时完成:
// The presence of the `done` parameter indicates to Jasmine that
// the test is asynchronous
it('should run the getNextPage function', function(done) {
this.scope.getNextPage().then(function () {
this.scope.$digest();
console.log(this.anotherService.resources);
expect(this.anotherService.resources).toEqual(3);
done(); // indicate to Jasmine that the asynchronous test has completed
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.