我可以找到很多来自控制器的单个http调用的示例以及如何测试它们,但没有多个测试的示例。
我的第一个测试在控制器中没有Product.find(10)
的情况下正常工作。当我添加该行时,第一个测试会崩溃。
错误:
Error: Unexpected request: GET 0.0.0.0:3000/api/products
No more request expected
和
Error: Unexpected request: GET 0.0.0.0:3000/api/products
No more request expected
我已经尝试了很多东西:包括在每个之前,这给了我一个未定义的错误,我尝试使用expect而不是when,我尝试将两个whens添加到两个测试,以及上面的组合。我显然做了一些非常错误的事情,但作为一个有角度的新手,很难确切地知道那可能是什么,特别是缺少示例..我只是想让我的第一个测试通过Product.find(10)
以下是我的测试:
'use strict';
describe('productsController', function() {
var scope, $httpBackend;
var api_root = '0.0.0.0:3000/api/';
beforeEach(angular.mock.module('sprangularApp'));
beforeEach(angular.mock.inject( function($rootScope, $controller, _$httpBackend_) {
$httpBackend = _$httpBackend_;
//Get mock jsons
jasmine.getJSONFixtures().fixturesPath='base/js/tests/api_mock';
scope = $rootScope.$new();
$controller('productsController', {$scope: scope});
}));
//Start Tests
it('Should be array of all products', function() {
$httpBackend.when('GET', api_root + 'products').respond(
getJSONFixture('products.json')
);
$httpBackend.flush();
expect(scope.products[3].name).toBe('Ruby on Rails Bag');
});
it('Should instantiate a new product object from json data', function() {
$httpBackend.when('GET', api_root + 'products/10').respond(
getJSONFixture('10.json')
);
$httpBackend.flush();
expect(scope.currentProduct.name).toBe('Spree Ringer T-Shirt');
});
});
我正在测试的控制器:
// Generated by CoffeeScript 1.6.3
(function() {
var sprangularControllers;
sprangularControllers = angular.module('sprangularControllers', ['sprangularServices']);
sprangularControllers.controller('productsController', [
'$scope', 'Product', function($scope, Product) {
Product.products_with_meta().$promise.then(function(response) {
return $scope.products = response.products;
});
return Product.find(10);
}
]);
}).call(this);
带资源请求的工厂:
sprangularServices = angular.module('sprangularServices', ['ngResource'])
sprangularServices.factory('Defaults', ->
api_url: "0.0.0.0:3000/api/"
)
sprangularServices.factory('Product', ($resource, Defaults) ->
# $resource(Defaults.api_url + 'products.json')
class Product
constructor: ->
@service = $resource(Defaults.api_url + 'products/:id', {id: '@id'})
this.products_with_meta = ->
service = $resource(Defaults.api_url + 'products')
service.get()
this.find = (id) ->
service = $resource(Defaults.api_url + 'products/:id', {id: id})
service.get()
)
根据迈克尔的建议,我已经编辑了我的测试,但是我仍然得到完全相同的结果:
'use strict';
describe('productsController', function() {
var $rootScope, $httpBackend, createController;
var api_root = '0.0.0.0:3000/api/';
beforeEach(angular.mock.module('sprangularApp'));
beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
//Get mock jsons
jasmine.getJSONFixtures().fixturesPath='base/js/tests/api_mock';
$rootScope = $injector.get('$rootScope');
var $controller = $injector.get('$controller');
createController = function() {
return $controller('productsController', {'$scope' : $rootScope });
};
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
//Start Tests
it('Should be array of all products', function() {
$httpBackend.when('GET', api_root + 'products').respond(
getJSONFixture('products.json')
);
var controller = createController();
$httpBackend.flush();
expect($rootScope.products[3].name).toBe('Ruby on Rails Bag');
});
it('Should instantiate a new product object from json data', function() {
$httpBackend.when('GET', api_root + 'products/10').respond(
getJSONFixture('10.json')
);
var controller = createController();
$httpBackend.flush();
expect($rootScope.currentProduct.name).toBe('Spree Ringer T-Shirt');
});
});
答案 0 :(得分:2)
以这种方式构建我的测试似乎解决了这个问题:
'use strict';
describe('productsController', function() {
var $rootScope, $httpBackend, createController;
var api_root = '0.0.0.0:3000/api/';
beforeEach(angular.mock.module('sprangularApp'));
beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
//Get mock jsons
jasmine.getJSONFixtures().fixturesPath='base/js/tests/api_mock';
$rootScope = $injector.get('$rootScope');
var $controller = $injector.get('$controller');
createController = function() {
return $controller('productsController', {'$scope' : $rootScope });
};
$httpBackend.when('GET', api_root + 'products').respond(
getJSONFixture('products.json')
);
$httpBackend.when('GET', api_root + 'products/10').respond(
getJSONFixture('10.json')
);
var controller = createController();
$httpBackend.flush();
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
$httpBackend.resetExpectations();
});
//Start Tests
it('Should be array of all products', function() {
expect($rootScope.products[3].name).toBe('Ruby on Rails Bag');
});
it('Should instantiate a new product object from json data', function() {
expect($rootScope.currentProduct.name).toBe('Spree Ringer T-Shirt');
});
});
答案 1 :(得分:1)
我认为的顺序定义响应,执行 http调用, flush 并执行测试是不对的。
定义http调用应如何响应
$httpBackend.when('GET', api_root + 'products').respond(
getJSONFixture('products.json')
);
通过您的代码进行调用
$controller('productsController', {$scope: scope});
刷新httpBackend(例如模拟$ http的异步行为)
$httpBackend.flush();
进行测试
expect(scope.products[3].name).toBe('Ruby on Rails Bag');
因为你的控制器在他的构造函数中进行了后端调用,并且在定义响应应该是什么之前进行了实例化,所以你得到了错误。
更多信息和例子非常接近您的使用案例:http://docs.angularjs.org/api/ngMock。$ httpBackend