2015-09-22 21 views
9

Chúng tôi hiện đang cố gắng thử nghiệm các dịch vụ góc cạnh của chúng tôi sử dụng lời hứa để trả về giá trị cho bộ điều khiển. Vấn đề là các chức năng chúng tôi đính kèm vào .then không được gọi trong Jasmine.

Chúng tôi thấy rằng việc thêm $ rootScope.digest() vào hàm sau khi lời hứa được trả lại cho phép lời hứa đồng bộ được gọi tuy nhiên nó vẫn không hoạt động đối với lời hứa Không đồng bộ.

Mã này cho đến nay là

beforeEach(inject(function (Service, $rootScope) 
    { 
     service = Service; 
     root = $rootScope; 
    })); 

    it('gets all the available products', function (done) 
    { 
     service.getData().then(function (data) 
     { 
      expect(data).not.toBeNull(); 
      expect(data.length).toBeGreaterThan(0); 
      done(); 
     }); 
     root.$digest(); 
    }); 

Trong trường hợp này hứa hẹn được gọi tốt, nhưng nếu nó là không đồng bộ nó sẽ không được gọi vì lời hứa vẫn chưa sẵn sàng cho "tiêu hóa" bởi thời điểm gốc. $ digest() được gọi.

Có cách nào để biết thời điểm lời hứa sau khi được giải quyết để tôi có thể gọi điện thoại thông báo không? Hoặc có thể một cái gì đó sẽ tự động làm điều đó? Cảm ơn bạn;)

một phần của dịch vụ chúng tôi phải kiểm tra (xử lý lỗi bị loại bỏ):

var app = angular.module('service', []); 

/** 
* Service for accessing data relating to the updates/downloads 
* */ 
app.factory('Service', function ($q) 
{ 
    ... init 

    function getData() 
    { 
     var deffered = $q.defer(); 

     var processors = [displayNameProc]; 

     downloads.getData(function (err, data) 
     { 
      chain.process(processors, data, function (err, processedData) 
      { 
       deffered.resolve(processedData); 
      }); 
     }); 

     return deffered.promise; 
    } 
    ... 

Trong trường hợp có một vấn đề là khi service.getData là async lời hứa đã được giải quyết nhưng các chức năng kèm theo lời hứa đó từ mã thử nghiệm không được gọi vì gốc. $ digest đã được gọi. Hy vọng điều này sẽ cho biết thêm

Cách giải quyết

var interval; 
beforeEach(inject(function ($rootScope) 
{ 
    if(!interval) 
    { 
     interval = function() 
     { 
      $rootScope.$digest(); 
     }; 
     window.setInterval(interval, /*timing*/); 
    } 
})); 

tôi đã kết thúc bằng cách sử dụng workaround ở trên để gọi tiêu hóa nhiều lần vì vậy mỗi lớp hứa hẹn sẽ nhận được một cơ hội để chạy ... nó không lý tưởng hoặc khá nhưng nó hoạt động cho kỳ thi ...

+0

Bạn đang chế giễu dịch vụ của bạn và do đó lời hứa trả lại? – CainBot

+0

Không, tôi đang cố gắng thử nghiệm dịch vụ thực tế. – BrendanM

+0

Nếu bạn đang thử nghiệm dịch vụ thực tế và nó đang sử dụng nội bộ dịch vụ $ http thì tôi tin rằng một thông báo sẽ bị khởi động bởi angularjs khi cuộc gọi từ xa thành công hoặc không thành công. – CainBot

Trả lời

0

bạn nên di chuyển khẳng định của bạn bên ngoài thì tôi tin rằng:

beforeEach(inject(function (Service, $rootScope) 
{ 
    service = Service; 
    root = $rootScope; 
})); 

it('gets all the available products', function (done) 
{ 
    var result; 
    service.getData().then(function (data) 
    { 
     result = data; 
     done(); 
    }); 

    root.$digest(); 

    expect(result).not.toBeNull(); 
    expect(result .length).toBeGreaterThan(0); 
}); 

Cập nhật

Đập plunkr khỏi nhận xét bên dưới để cho biết cách bạn có thể kiểm tra cuộc gọi không đồng bộ.

Thêm $ timeout với dịch vụ:

var app = angular.module('bad-service', []); 

app.service('BadService', function ($q, $interval, $timeout) 
{ 
    this.innerPromise = function(){ 
     var task = $q.defer(); 
     console.log('Inside inner promise'); 

     $timeout(function() { 
     console.log('Inner promise timer fired'); 
     task.resolve(); 
     }, 500); 
     // $interval(function(){ 

     // }, 500, 1); 
     return task.promise; 
    } 
}); 

Và tôi đỏ bừng timeout $ trước khi khẳng định:

beforeEach(module('test')); 


describe('test', function(){ 
    var service, root, $timeout; 

    beforeEach(inject(function (Service, $rootScope, _$timeout_) 
    { 
     $timeout = _$timeout_; 
     console.log('injecting'); 
     service = Service; 
     root = $rootScope; 
    })); 

    /** 
    Test one 
    */ 
    it('Should work', function(done){ 
     console.log('Before service call'); 
     service.outerPromise().then(function resolve(){ 
     console.log('I should be run!'); 
     expect(true).toBeTruthy(); 
     done(); 
     }); 
     // You will have to use the correct "resolve" here. For example when using: 
     // $httpbackend - $httpBackend.flush(); 
     // $timeout- $timeout.flush(); 
     $timeout.flush(); 

     console.log('After service call'); 
    }); 
}); 
+0

Thật không may này wont làm việc trong trường hợp của chúng tôi bởi vì getData là async có nghĩa là kết quả sẽ được null bởi thời gian nó đạt đến mong đợi đầu tiên (result) .not.toBeNull(); – BrendanM

+0

Giải pháp này dành riêng cho các cuộc gọi không đồng bộ; bạn đã thử nghiệm nếu nó không hoạt động? Sự kết hợp của 'done();' và 'root. $ digest();' sẽ đảm bảo rằng cuộc gọi async của bạn được giải quyết trước khi các kỳ vọng được gọi. –

+0

Vâng xin lỗi, tôi thấy rằng bây giờ bệnh cho nó một shot – BrendanM

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