我遵循angular-test-patterns指南,并在我的第一个控制器测试中使其工作。但是当我编写下一个测试时,我得到了错误:
TypeError: 'undefined'不是一个对象(求值'$scope.pages.$promise')
我知道问题是下面这行:
美元范围。
<scope.pages.$promise;>
但我不知道如何处理这个,特别是因为我是非常新的测试问题与JavaScript。我在寻找一种正确可行的方法来做这件事,给我指明正确的方向。
控制器:
angular.module('webvisor')
.controller('page-list-controller', function($scope,Page){
$scope.pages = Page.query();
$scope.busy = $scope.pages.$promise;
});
服务:angular.module('webvisor').
factory('Page', ['$resource', 'apiRoot', function($resource, apiRoot) {
var apiUrl = apiRoot + 'pages/:id/:action/#';
return $resource(apiUrl,
{id: '@id'},
{update: {method: 'PUT'}}
);
}]);
测试:'use strict';
describe('Controller: page-list-controller', function () {
var ctrl, scope, rootScope, Page;
beforeEach(function () {
module('webvisor');
module(function ($provide) {
$provide.value('Page', new MockPage());
});
inject(function ($controller, _Page_) {
scope = {};
rootScope = {};
Page = _Page_;
ctrl = $controller('page-list-controller', {
$scope: scope,
$rootScope: rootScope
});
});
});
it('should exist', function () {
expect(!!ctrl).toBe(true);
});
describe('when created', function () {
// Add specs
});
});
模拟:MockPage = function () {
'use strict';
// Methods
this.query = jasmine.createSpy('query'); // I dont know if this is correct
return this;
};
使用Mox,您的解决方案看起来像这样:
describe('Controller: page-list-controller', function () {
var mockedPages = []; // This can be anything
beforeEach(function () {
mox
.module('webvisor')
.mockServices('Page') // Mock the Page service instead of $httpBackend!
.setupResults(function () {
return {
Page: { query: resourceResult(mockedPages) }
};
})
.run();
createScope();
createController('page-list-controller');
});
it('should get the pages', function () {
expect(this.$scope.pages).toEqual(resourceResult(mockedPages));
});
});
正如你所看到的,Mox已经抽象掉了所有的样板注入,比如$rootScope
和$controller
。此外,还支持开箱即用的测试资源和承诺。
我建议您不要将资源结果直接放在作用域上,而是将其解析为承诺:
$scope.busy = true;
Pages.query().$promise
.then(function (pages) {
$scope.pages = pages;
$scope.busy = false;
});
Mox测试是这样的:
expect(this.$scope.busy).toBe(true);
this.$scope.$digest(); // Resolve the promise
expect(this.$scope.pages).toBe(mockedPages);
expect(this.$scope.busy).toBe(false);
注意:您也可以将createScope()
的结果存储到$scope
变量中并在任何地方重用,而不是访问this.$scope
。
经过一些研究和许多尝试和错误案例后,我用一个可能的解决方案回答自己,但我希望很快找到一些更可用且不太重复的解决方案。现在,我对此很满意,使用$httpBackend
。
'use strict';
describe('Controller: page-list-controller', function () {
var ctrl, scope, rootScope, httpBackend, url;
beforeEach(function () {
module('webvisor');
inject(function ($controller, $httpBackend, apiRoot) {
scope = {};
rootScope = {};
httpBackend = $httpBackend;
url = apiRoot + 'pages/#';
ctrl = $controller('page-list-controller', {
$scope: scope,
$rootScope: rootScope
});
});
});
it('should exist', function () {
expect(!!ctrl).toBe(true);
});
describe('when created', function () {
it('should get pages', function () {
var response = [{ 'name': 'Page1' }, { 'name': 'Page2' }];
httpBackend.expectGET(url).respond(200, response);
httpBackend.flush();
expect(scope.pages.length).toBe(2);
});
});
});
我在阅读这个问题时找到了这个解决方案。这工作得很好,现在,我很满意。在以后,我尝试了一些类似的东西:
- angular-easy-test
- 混合氧化物燃料