2014-01-13 61 views
1

我是新来的角和TDD,我正在寻找一些帮助与我的一个测试。我正在与API后端进行会谈的应用程序,我用一些js设备嘲笑了这个后端。angularJS测试工厂,返回undefined get() - 异步问题

JSON数据:

{ 
"count": 25, 
"total_count": 32, 
"current_page": 1, 
"per_page": 25, 
"pages": 2, 
"products": [ 
    {"name": "test"}, 
    {}, 
    {}, 
    {}, 
]} 

产品每个都有一些数据,我只概述以上的结构。

我通过测试(茉莉花)

'use strict'; 

describe('productsController', function() { 

    var scope, $httpBackend; 

    beforeEach(angular.mock.module('sprangularApp')); 

    beforeEach(angular.mock.inject(function($rootScope, $controller, _$httpBackend_) { 
     //Actual API 0.0.0.0:3000/api/, below is mock data only. 
     var api_root = '0.0.0.0:3000/api/' 

     $httpBackend = _$httpBackend_; 

     //Get mock jsons 
     jasmine.getJSONFixtures().fixturesPath='base/js/tests/api_mock'; 

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

     scope = $rootScope.$new(); 
     $controller('productsController', {$scope: scope}); 
    })); 

    //Start Tests 
    it('Should fetch all products', function() { 
     // $httpBackend.flush(); 
     // expect(scope.products[5].name).toBe('Ruby on Rails Baseball Jersey'); 
     $httpBackend.flush(); 
     expect(scope.products.count).toBe(25); 

     expect(scope.products.products[0].id).toBe(1); 
     expect(scope.products.products[0].name).toBe('Ruby on Rails Tote'); 

     expect(scope.products.products[9].id).toBe(5); 
     expect(scope.products.products[9].permalink).toBe('ruby-on-rails-ringer-t-shirt'); 
    }); 
}); 

控制器:

// Generated by CoffeeScript 1.6.3 
(function() { 
var sprangularServices; 

sprangularServices = angular.module('sprangularServices', ['ngResource']); 

sprangularServices.factory('Defaults', function() { 
    return { 
    api_url: "0.0.0.0:3000/api/" 
    }; 
}); 

sprangularServices.factory('Product', function($resource, Defaults) { 
    var Product; 
    return Product = (function() { 
    function Product() { 
     this.service = $resource(Defaults.api_url + 'products/:id', { 
     id: '@id' 
     }); 
    } 

    Product.prototype.create = function(attrs) { 
     new this.service({ 
     product: attrs 
     }).$save(function(product) { 
     return attrs.id = product.id; 
     }); 
     return attrs; 
    }; 

    Product.all = function() { 
     var data, service; 
     service = $resource(Defaults.api_url + 'products'); 
     data = service.get(); 
    }; 

    return Product; 

    })(); 
}); 

}).call(this); 

测试:

'use strict'; 

describe('productsController', function() { 

    var scope, $httpBackend; 

    beforeEach(angular.mock.module('sprangularApp')); 

    beforeEach(angular.mock.inject(function($rootScope, $controller, _$httpBackend_) { 
     //Actual API 0.0.0.0:3000/api/, below is mock data only. 
     var api_root = '0.0.0.0:3000/api/' 

     $httpBackend = _$httpBackend_; 

     //Get mock jsons 
     jasmine.getJSONFixtures().fixturesPath='base/js/tests/api_mock'; 

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

     scope = $rootScope.$new(); 
     $controller('productsController', {$scope: scope}); 
    })); 

    //Start Tests 
    it('Should fetch all products', function() { 
     // $httpBackend.flush(); 
     // expect(scope.products[5].name).toBe('Ruby on Rails Baseball Jersey'); 
     $httpBackend.flush(); 
     expect(scope.products.count).toBe(25); 

     expect(scope.products.products[0].id).toBe(1); 
     expect(scope.products.products[0].name).toBe('Ruby on Rails Tote'); 

     expect(scope.products.products[9].id).toBe(5); 
     expect(scope.products.products[9].permalink).toBe('ruby-on-rails-ringer-t-shirt'); 
    }); 
}); 

上面的代码正常工作和测试出色地通过。我想不过做的是有Product.all返回JS内的产品阵列,而不同类产品中的元信息数等

我修改了服务,这样它会返回:

Product.all = function() { 
    var data, service; 
    service = $resource(Defaults.api_url + 'products'); 
    data = service.get(); 
    return data.products 
    }; 

它似乎data.products是未定义的,因为是数据,我有一种感觉,这可能与刷新有关,但我不确定,为什么data.products不返回包含在JSON中的数组?它与get()的同步性有关。

+0

到anyon e在getJSONFixtures上未定义,它被捆绑在jasmine-jquery中https://github.com/velesin/jasmine-jquery –

回答

2

我认为这是一个同步问题。

这是做你想做的吗?

Product.all = function() { 
    var data, service; 
    service = $resource(Defaults.api_url + 'products'); 
    return service.get().$promise.then(function (result) { 
    return result.products; 
    }); 
}; 

编辑

如果你正在做的是把对$scopeProduct.all的结果,那么你可以(未经测试)这样做:

Product.all = function() { 
    var data, service; 
    var products = []; 
    service = $resource(Defaults.api_url + 'products'); 
    service.get().$promise.then(function (result) { 
    for (var i in result.products) { 
     products.push(result.products[i]); 
    } 
    }); 
    return products; 
}; 

如果你希望做别的我会做的(未经测试):

$scope.$watch(Product.all, function (value) { 
    $scope.products = value; 
    // other stuff here to products 
}/* , true */); // You probably need to deeply watch the array for changes - I can't test it at the moment. 
+0

我实际上正在编写类似的东西,这正是我想到的。然而,这说,使用你的确切代码后,我仍然没有定义。它肯定是一个同步的问题,因为console.log在它之后写的另一个console.log之后返回get ...任何想法,为什么我仍然得到错误? – Melbourne2991

+0

似乎控制器调用$ scope.products =,在检索数据之前调用变量赋值,也许我必须将逻辑移到控制器上。 – Melbourne2991

+0

那么要在控制器中使用承诺,承诺结果中的任务。你懂我的意思吗? –