2015-07-01 15 views
20

Tôi cố gắng để thử nghiệm một dịch vụ được sử dụng $http

var APIClient = function($http) { 
    this.send = function(data) { 
     $http({ 
      method: data.method, 
      url: data.url, 
      headers: data.headers, 
      data: data.data 
     }).success(function(response, status) { 
      data.success(response, status); 
     }).error(function(response, status) { 
      data.error(response, status); 
     }); 
    } 
} 

angular.module('api.client', []).factory('APIClient', ['$http' 
    function($http) { 
     var client = new APIClient($http); 

     return { 
      send: function(data) { 
       return client.send(data); 
      }, 
     } 

    } 
]); 

Và kiểm tra

describe('send', function() { 

     var apiClient, $httpBackend; 

     beforeEach(module('compare')); 

     beforeEach(inject(function($injector) { 
      $httpBackend = $injector.get('$httpBackend'); 
      apiClient = $injector.get('APIClient'); 
     })); 

     it('Should check if send() exists', function() { 
      expect(apiClient.send).toBeDefined(); 
     }); 

     it('Should send GET request', function(done) { 
      var url = '/'; 

      $httpBackend.expect('GET', url).respond({}); 

      apiClient.send({ 
       url: url, 
       success: function(data, status) { 
        console.log(status); 
        done(); 
       }, 
       error: function(data, status) { 
        console.log(status); 
        done(); 
       } 
      }); 

      $httpBackend.flush(); 
     }); 
    }); 

Nhưng tôi luôn luôn có lỗi này

PhantomJS 1.9.8 (Mac OS X) send Should send GET request FAILED 
     Error: Unexpected request: GET templates/test.html 
     Expected GET/

Url dự kiến ​​luôn là trạng thái cuối cùng trong số app.js Trong trường hợp này

// Ionic Starter App 

// angular.module is a global place for creating, registering and retrieving Angular modules 
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html) 
// the 2nd parameter is an array of 'requires' 
// 'starter.services' is found in services.js 
// 'starter.controllers' is found in controllers.js 

angular.module('compare', 
    [ 
     'ionic', 
     'manager.user', 
     'api.client', 
     'api.user', 
     'api.compare', 
     'user.controllers', 
     'test.controllers' 
    ] 
) 

    .run(function ($ionicPlatform) { 
     $ionicPlatform.ready(function() { 
      // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard 
      // for form inputs) 
      if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) { 
       cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); 
      } 
      if (window.StatusBar) { 
       // org.apache.cordova.statusbar required 
       StatusBar.styleLightContent(); 
      } 
     }); 
    }) 

    .config(function ($stateProvider, $urlRouterProvider) { 

     // Ionic uses AngularUI Router which uses the concept of states 
     // Learn more here: https://github.com/angular-ui/ui-router 
     // Set up the various states which the app can be in. 
     // Each state's controller can be found in controllers.js 
     $stateProvider 

      // setup an abstract state for the tabs directive 
      .state('tab', { 
       url: "/tab", 
       abstract: true, 
       templateUrl: "templates/tabs.html" 
      }) 

      // Each tab has its own nav history stack: 

      .state('tab.dash', { 
       url: '/dash', 
       views: { 
        'tab-dash': { 
         templateUrl: 'templates/tab-dash.html', 
         controller: 'DashCtrl' 
        } 
       } 
      }) 

      .state('subscription', { 
       url: '/subscription', 
       templateUrl: 'templates/subscription.html', 
       controller: 'SubscriptionCtrl' 
      }) 

      .state('login', { 
       url: '/login', 
       templateUrl: 'templates/login.html', 
       controller: 'LoginCtrl' 
      }) 

      .state('test-compare', { 
       url: '/test/compare', 
       templateUrl: 'templates/test.html', 
       controller: 'TestCompareCtrl' 
      }) 

     // if none of the above states are matched, use this as the fallback 
     $urlRouterProvider.otherwise('/login'); 

    }); 

Tôi không hiểu tại sao các url đang thay đổi Tôi cho / và nó kiểm tra templates/test.html mà luôn luôn là người cuối cùng mẫu nhà nước

+0

Khi bạn tiêm '$ httpBackend' trong các thử nghiệm của chúng tôi, nó chặn tất cả các yêu cầu http. Vì vậy, rõ ràng bạn có một số mã (không phải từ APIClient nếu đây là mã duy nhất của nó được trình bày trong OP) mà gây nên các trạng thái. Bạn có thể cung cấp mã định nghĩa mô-đun 'so sánh' không? –

+0

@KirillSlatin Tôi vừa cập nhật mã cuối cùng sẽ là toàn bộ app.js – Ajouve

+0

Tại sao bạn khai báo dịch vụ «APIClient' trong mô-đun' api.client', nhưng gọi 'so sánh' trong bộ thử nghiệm cho dịch vụ? –

Trả lời

6

Iss chính của bạn ue đây là dòng này:

beforeEach(module('compare')); 

Bạn đang tải toàn bộ ứng dụng của bạn ở đây thay vì chỉ các apiClient. Về cơ bản, bạn đang làm một thử nghiệm hội nhập thổi đầy đủ, thay vì một bài kiểm tra đơn vị.

Bạn nên chỉ api.client tải.

beforeEach(module('api.client')); 

Something hữu ích cần lưu ý, bạn cũng có thể làm điều gì đó như:

$httpBackend.whenGET(/templates\/(.*)/).respond(''); mà về cơ bản bỏ qua tất cả các mẫu mà có được nạp bởi router, bộ điều khiển, hoặc chỉ thị. Nếu bạn làm điều này mặc dù, nó vẫn sẽ không được coi là một thử nghiệm đơn vị, bởi vì bạn không nghiêm túc kiểm tra chỉ APIClient của bạn.

Một lưu ý hữu ích:

Bất cứ điều gì bạn thực hiện bên trong .run hoặc .config không phải là một chức năng annonymous, như vậy bạn có thể thử nó.

Một ví dụ về điều này sẽ được thực hiện:

.config(CompareStateLoader); 

CompareStateLoader.$inject = [ 
    '$stateProvider', 
    '$urlRouterProvider' 
]; 

function CompareStateLoader(
    $stateProvider, 
    $urlRouterProvider 
){ 
    //configure states here 
} 

Việc làm này sẽ cho phép bạn để thử CompareStateLoader và tải này trong runner thử nghiệm của bạn.

Để biết thêm thông tin về vấn đề này, vui lòng xem góc Style Guide here John Papa của.

0
var apiClient, $httpBackend, $loc; 

    beforeEach(module('compare')); 

    beforeEach(inject(function($injector, $location) { 
     $httpBackend = $injector.get('$httpBackend'); 
     apiClient = $injector.get('APIClient'); 
     $loc = $location; 
    })); 


it ('Should send GET request', function(done) { 
     expect($loc.path()).toEqual(''); 
     var url = '/'; 

     $httpBackend.expect('GET', $loc.path('/')).respond({}); 

     apiClient.send({ 
      url: url, 
      success: function(data, status) { 
       console.log(status); 
       done(); 
      }, 
      error: function(data, status) { 
       console.log(status); 
       done(); 
      } 
     }); 

     $httpBackend.flush(); 
    }); 

Sửa Bạn nên sử dụng angular-mock để sử dụng $ location

beforeEach(inject(function(_$httpBackend_, APIClient) { 
     $httpBackend = _$httpBackend_; 
     apiClient = APIClient; 
    })); 
+0

Hãy thử với 'mong đợi ($ loc.path()). ToEqual ('');' và cho tôi phản hồi – gr3g

+0

'mong đợi ($ loc.path()). ToEqual ('');' works nhưng '$ loc.path ('/')' trả về một đối tượng và tôi có lỗi 'Expected GET [object Object]' và '$ loc.path ('/'). url()' returns '/' – Ajouve

+0

I 'không sử dụng bộ định tuyến UI, có thể là lý do tại sao có lỗi – gr3g

1

tôi sẽ đề nghị để biên dịch tất cả các mẫu của bạn vào tập tin JS (ví dụ với grunt "html2js" nhiệm vụ hoặc tiền xử lý nghiệp "ng-html2js") và không có đau đầu với các mẫu geting.

Hoặc bạn cũng có thể sử dụng passthrough

$httpBackend.when('GET', /\.html$/).passThrough() 

Ví dụ - http://plnkr.co/edit/pbjcDl?p=preview

Nhưng tôi sẽ đề nghị để sử dụng tùy chọn đầu tiên.

0

Thêm dòng này vào trước mỗi khối - $ httpBackend.expect ('GET', "templates/test.html"). Answer (200);

Các vấn đề liên quan