首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多个get请求一个控制器:意外请求,单元测试- AngularJS

多个get请求一个控制器:意外请求,单元测试- AngularJS
EN

Stack Overflow用户
提问于 2014-01-13 23:29:46
回答 2查看 7.3K关注 0票数 3

我可以找到大量来自控制器的单个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,我尝试将两者都添加到两个测试中,以及以上两种方法的组合。我显然在做一些非常错误的事情,但作为一个棱角分明的新手,很难准确地计算出这可能是什么,特别是在缺乏例子的情况下。我只是想让我的第一个测试通过Product.find(10)

以下是我的测试:

代码语言:javascript
复制
'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');
    });
}); 

我正在测试的控制器:

代码语言:javascript
复制
// 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);

以及具有资源请求的工厂:

代码语言:javascript
复制
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()
)

根据michael的建议,我已经修改了我的测试,但是我仍然得到了完全相同的结果:

‘使用严格的’;

代码语言:javascript
复制
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');
    });
}); 
EN

回答 2

Stack Overflow用户

发布于 2014-01-14 10:21:21

以这种方式组织我的测试似乎解决了这个问题:

代码语言:javascript
复制
'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');
    });
}); 
票数 2
EN

Stack Overflow用户

发布于 2014-01-14 04:11:35

我认为定义响应、做http调用、刷新和做测试的顺序是不正确的。

  1. 定义http调用应该如何响应。

$httpBackend.when('GET',api_root + 'products').respond( getJSONFixture('products.json') );

  • 从您的代码执行调用

$controller('productsController',{$scope: scope});

  • 刷新httpBackend (例如模拟$http的异步行为)

$httpBackend.flush();

  • do测试

expect(.toBe e.products3.name).toBe(‘Ruby on Rails Bag');

因为您的控制器在其构造函数中执行了一个后端调用,并且在您定义响应应该是什么之前被实例化,所以您得到了错误。

更多信息和一个非常接近您的用例的示例:http://docs.angularjs.org/api/ngMock.$httpBackend

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21095064

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档