2014-12-06 20 views
9

Tôi hiện đang thử đơn vị kiểm tra dịch vụ góc của mình bằng cách sử dụng SinonJS, nhưng đã gặp sự cố và hy vọng ai đó có thể làm sáng tỏ lý do tại sao điều này xảy ra. Tôi đã xây dựng lại dự án hiện tại của mình để minh họa vấn đề trong tầm tay.Thử nghiệm đơn vị góc - Phương pháp mô phỏng/đóng cửa trong cùng một dịch vụ

Tôi cũng đã cung cấp một DEMO

Tôi có một dịch vụ, peopleService:

(function(){ 

    angular.module('myApp') 
    .factory('peopleService', peopleService); 

    peopleService.$inject = ['$q']; 

    function peopleService ($q){ 
     var people = ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie']; 

     // in actual project, this makes an http request 
     function getFamily() { 
     return people; 
     } 

     function getAdults(){ 
     var family = getFamily(); 
     return family.filter(function (person){ 
      return person === 'Homer' || person === 'Marge'; 
     }); 
     } 

     return { 
     getFamily: getFamily, 
     getAdults: getAdults 
     } 
    } 

}()); 

Trong dịch vụ này, phương pháp của tôi getAdults sử dụng getFamily, lọc các kết quả, và trả về dữ liệu.

Trong thử nghiệm đơn vị của mình, tôi đang cố gắng giả lập getFamily và xem liệu phương pháp đó có đang được gọi hay không. Bây giờ đây là nơi mà các vấn đề trình bày chính nó ...

Điều đầu tiên tôi đã cố gắng đã được loại bỏ dần từng phương pháp này và ghi đè lên các phương pháp hiện hành, như vậy:

beforeEach(function(){ 
    module('myApp'); 

    inject(function (_peopleService_){ 
    peopleService = _peopleService_; // get the service 
    sinon.stub(peopleService, 'getFamily'); // stub it 
    }); 
}); 

sau đó tôi đi để kiểm tra xem getAdults gọi getFamily phương pháp:

it('getAdults should call "getFamily" once', function(){ 
    peopleService.getAdults(); 
    expect(peopleService.getFamily.calledOnce).toBe(true); 
}); 

thử nghiệm thất bại và phương pháp stubbed không được gọi là ...

tôi gỡ lỗi và tìm ra t mũ mặc dù chức năng có trong thực tế đã thay đổi: enter image description here

Dịch vụ này vẫn giữ một tham chiếu (đóng cửa) với những gì phương pháp được sử dụng là khi dịch vụ được tạo ra:

enter image description here

suy nghĩ ban đầu của tôi là Tôi đã không khai báo đúng phương pháp. Sau đó tôi đã cố gắng ghi đè phương pháp bằng cách sử dụng $provide ($provide.value) cũng như $injector decorator và tôi đã nhận được kết quả tương tự (đóng cửa được giữ trong phương thức gốc).

Một giải pháp này sẽ được sử dụng this:

function getAdults(){ 
    var family = this.getFamily(); // <-- by using this.getFamily would reference the mock 
    return family.filter(function (person){ 
     return person === 'Homer' || person === 'Marge'; 
    }); 
    } 

Tuy nhiên, tôi không hiểu tại sao tôi phải làm điều này.

Nói tóm lại, không ai biết:

  • làm thế nào để thử phương pháp khác trong cùng một dịch vụ mà không cần phải sử dụng this
  • làm thế nào để thử ra một biến đóng cửa trong một thử nghiệm đơn vị

Cảm ơn bạn rất nhiều vì đã dành thời gian.

+0

dường như plunker bạn không có sẵn nữa – sam

Trả lời

5

Khi bạn đưa phương thức lên đối tượng, thuộc tính của đối tượng đó được ghi đè lên, không phải hàm ban đầu mà nó tham chiếu.

Lấy ví dụ, mã này:

function myFunction() {}; 
var myObj = { prop: myFunction }; 

myObj.prop === myFunction; // true 
myObj.prop = 'changed'; 

typeof myFunction === 'function'; // true 
myObj.prop === myFunction; // false 

Thay đổi myObj.prop không thay đổi chức năng ban đầu, myFunction vẫn còn tồn tại theo đúng nghĩa của nó. Tuy nhiên, myObj.prop đã mất tham chiếu đến myFunction. Nếu đây là trong thế giới tội lỗi, thì chỉ cần thay đổi tham chiếu của myObj.prop thành một đối tượng sơ khai.

Đây là lý do tại sao khi kiểm tra mã trong một dịch vụ trong đó kêu gọi một chức năng trong cùng một dịch vụ, mã mà cần phải tham khảo cùng một đối tượng được trả về bởi các dịch vụ. Nếu bạn muốn tránh sử dụng các từ khóa this ở khắp mọi nơi, bạn có thể cấu trúc dịch vụ của bạn như sau:

angular.module('myApp') 
    .factory('peopleService', peopleService); 

peopleService.$inject = ['$q']; 

function peopleService ($q){ 
    var service = { 
    getFamily: getFamily, 
    getAdults: getAdults 
    }; 

    return service; 

    function getFamily() { 
    // ... 
    } 

    function getAdults(){ 
    var family = service.getFamily(); // <-- reference service.getFamily() 
    // ... 
    } 
} 
+0

Tôi nghĩ rằng câu trả lời này sẽ nhận được phần thưởng, nó là khá rõ ràng và đầy đủ – sam

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