2014-01-13 5 views
1

저는 각도 및 TDD를 처음 사용하며 테스트 중 하나에 대한 도움을 찾고 있습니다. API 백엔드와 대화를하고있는 애플리케이션은이 백엔드를 일부 js 픽처처로 조롱했습니다.angularJS 테스트 팩토리, get() - async 문제 후 undefined 반환

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'); 
    }); 
}); 

위의 코드는 잘 작동 시험 비행 색상으로 전달합니다. 내가 그러나 할 싶습니다 계산 제품 등의 메타 정보없이 JS 내에서 제품의 배열을 반환 Product.all이있다 등은 반환 그래서 내가 서비스를 수정

:

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

를이 data.products가 정의되지 않은 것처럼 보입니다. 데이터와 마찬가지로, 이것은 flush와 관련이있을 수 있다는 느낌이 들지만 확실하지 않습니다. 왜 data.products가 JSON에 포함 된 배열을 반환하지 않습니까? 그것은 get()의 동조성과 관련이있다.

+0

To anyon 'getJSONFixtures'에서 정의되지 않은 것은 jasmine-jquery 안에 번들입니다. https://github.com/velesin/jasmine-jquery –

답변

2

동기 문제라고 생각합니다.

원하는대로 할 수 있습니까? 당신이하고있는 모두가 $scopeProduct.all의 결과를 두는 경우

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

편집

당신은 (안된)이 작업을 수행 할 수 있습니다

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

컨트롤러에서 약속을 사용하려면 약속의 결과에 배정. 내가 뭐라는지 알 겠어? –