2016-02-16 8 views
22

मैं जैस्मीन के साथ अपने ऐप का परीक्षण करने की कोशिश करता हूं और निम्न समस्या प्राप्त करता हूं:
मैं अपने वचन के then फ़ंक्शन में कुछ की गणना करूंगा। यही वह बिंदु है जहां मुझे अपने कोड का परीक्षण करने की आवश्यकता है।जैस्मीन एक वादा का परीक्षण करता है। फिर फ़ंक्शन

यहाँ मेरी नियंत्रक के कोड है:

TestCtrl.$inject = ["$scope", "TestService"]; 
    /* ngInject */ 
    function TestCtrl($scope, TestService) { 
    $scope.loadData = function() { 
     TestService.getData().then(function (response) { 
     $scope.data = response.data; 
     $scope.filtered = $scope.data.filter(function(item){ 
      if(item.id > 1000){ 
      return true; 
      } 
      return false; 
     }) 
     }); 
    } 
    } 

और मेरे जैस्मीन परीक्षण कोड:

describe('TestService tests', function() { 
    var $q; 
    beforeEach(function() { 
    module('pilot.fw.user'); 
    }); 
    beforeEach(inject(function (_$q_) { 
    $q = _$q_; 
    })); 
    describe('UserController Tests', function() { 

    beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) { 
     this.scope = $rootScope.$new(); 
     this.$rootscope = $rootScope; 
     this.$httpBackend = _$httpBackend_; 
     this.scope = $rootScope.$new(); 
     var TestServiceMock = { 
     getData: function() { 
      var deferred = $q.defer(); 
      var result = [{ 
      "id": 1720, 
      "user": 1132 
      }, 
      { 
       "id": 720, 
       "user": 132 
      }, { 
       "id": 1721, 
       "user": 1132 
      }]; 
      deferred.promise.data = result; 
      deferred.resolve(result); 
      return deferred.promise; 
     } 
     }; 
     this.controller = $controller('TestCtrl', { 
     '$scope': this.scope, 
     'TestService': TestServiceMock 
     }); 
    })); 

    it('test', function(){ 
     this.scope.loadData(); 
     expect(true).toBeTruthy(); 
    }) 
    }); 
}); 

अजीब बात मुझे समझ नहीं आता (कंसोल लॉग के साथ परीक्षण किया गया) है:

  • मेरा वादा बनाया गया है और
  • मेरा लोडडेटा फू nction कहा जाता है और यह TestService से GetData() फ़ंक्शन कॉल करेंगे
  • तो समारोह के अंदर सब कुछ, हालांकि मैं वादा के रूप में हल हो गई

तो मैं अंदर कोड का परीक्षण कर सकता है लौटने निष्पादित नहीं किया जाएगा तो फ़ंक्शन?
मदद के लिए धन्यवाद

उत्तर

29

चमेली 'यह विधि एक किया पैरामीटर है कि आप async परीक्षण के लिए कॉल कर सकते हैं

it('Should be async', function(done) { 
    someAsyncFunction().then(function(result) { 
    expect(result).toBe(true); 
    done(); 
    }); 
}); 

के रूप में गहरे रूप में आप चाहते जाने के लिए स्वतंत्र महसूस लेता है, बस सुनिश्चित करने के लिए किया कॉल करने के लिए जब सब खत्म हो गया है। जैस्मीन का डिफ़ॉल्ट टाइमआउट 5 सेकंड प्रति परीक्षण है, इसलिए यदि एसिंक सामग्री तब नहीं की जाती है तब तक जैस्मीन क्रैश हो जाएगा। आप इस सेटिंग को कॉन्फ़िगरेशन में बदल सकते हैं या इसे टर्मिनल में सेट कर सकते हैं।

यह आपको दिखा कैसे डिफ़ॉल्ट टाइमआउट अंतराल

describe("long asynchronous specs", function() { 
    var originalTimeout; 
    beforeEach(function() { 
    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; 
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; 
    }); 

    it("takes a long time", function(done) { 
    setTimeout(function() { 
     done(); 
    }, 9000); 
    }); 

    afterEach(function() { 
    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; 
    }); 
}); 

मुझे लगता है कि अगर यह 10 सेकंड में काम नहीं करता है, तो आप गलत तरीकों हो सकता है संभाल करने के लिए सीधे चमेली डॉक्स से है। विशेष रूप से यदि आप स्थानीय सर्वर/डीबी से बात कर रहे हैं। यह सामान केवल इतना लंबा लेना चाहिए यदि आप हेवी कंप्यूटेशंस कर रहे हैं, या एक बहुत ही महान इंटरनेट कनेक्शन के साथ बाहरी एपीआई मार रहे हैं। अगर सबकुछ स्थानीय है (या स्टब्बेड/मॉक!) तो 5-10 सेकेंड से अधिक कुछ भी एक निश्चित लाल झंडा है।

+0

यह ('परीक्षण', समारोह (किया) { TestServiceMock.getData() तो (समारोह (परिणाम) { console.log (परिणाम);। }); उम्मीद (सही) .toBeTruthy(); किया(); }) मैं इसे इस तरह से है, लेकिन मेरे कंसोल लॉग isn't की कोशिश की भी कहा जाता है ... एक ही समस्या के रूप में पहले:/ - CodeStyle के लिए खेद है - आपकी मदद के लिए टैंक –

+0

आप कर कॉल कर रहे हैं 'फिर' के बाहर! सुनिश्चित करें कि 'किया गया' आपके बाद के तरीकों के अंदर है :) –

+0

अन्यथा, वादे को हल करने से पहले आप निष्पादित कर रहे हैं, बहुत कम पता है कि इसका नतीजा क्या था। ध्यान दें कि मेरे उदाहरण में, मैं उम्मीद विधि में वादे का परिणाम पास करता हूं? यह केवल तभी काम करता है जब इसे हल किया जाता है, जो 'तो' –

0

आपके नियंत्रक के संबंध में, आपको ऐसे मूल्यों को 'वापस' करना चाहिए।

TestCtrl.$inject = ["$scope", "TestService"]; 
/* ngInject */ 
function TestCtrl($scope, TestService) { 
    $scope.loadData = function() { 
    // Return this call, since it will return a new promise 
    // This is what let's you do $scope.loadData.then() 
    return TestService.getData().then(function (response) { 
     // What you return in here will be the first argument 
     // of your then method, in the tests/any env 
     // Ex. return 'foo' 
     // will result in .then(result => result === 'foo') //=> true 
     // return one of these, i suggest the data, go SRP! 
     return $scope.data = response.data; 

     // I would do this stuff in a separate function, but you 
     // can return 'filtered' instead if you like. 
     // 
     // $scope.filtered = $scope.data.filter(function(item){ 
     // if(item.id > 1000){ 
     //  return true; 
     // } 
     // return false; 
     // }); 
    }); 
    } 
} 

याद रखें कि 'फिर' के बाद कुछ कहने का मतलब कुछ भी नहीं है, मूल्यों को 'फिर' कहा जाना चाहिए। इसके बाद, या इससे पहले नहीं। लेकिन इसके अंदर। टॉम ग्रीन की तरह और फ्रेडी गॉट फिंगर्ड में वह गरीब मूस।

+0

असफ़ल, मैं एफजीएफ संदर्भ के लिए अपवर्तना चाहता हूं, लेकिन मुझे नहीं लगता कि नियंत्रकों को कुछ भी वापस लौटना चाहिए जब तक वे –

1

मुझे बताएं कि मैं कोणीय 1.x और 2.x + परियोजनाओं के लिए क्या करता हूं। अपने एसिंक परीक्षणों में कॉलबैक/घोंसले से छुटकारा पाने के लिए कोणीय परीक्षण उपकरण का उपयोग करें। कोणीय 1.x में, इसका मतलब $ q और $ rootScope के संयोजन का उपयोग करना है। $ लागू करें()। कोणीय 2.x + में, इसका मतलब है कि fakeAsync जैसे कुछ का उपयोग करना।

From the Angular 1.x docs

it('should simulate promise', inject(function($q, $rootScope) { 
    var deferred = $q.defer(); 
    var promise = deferred.promise; 
    var resolvedValue; 

    promise.then(function(value) { resolvedValue = value; }); 
    expect(resolvedValue).toBeUndefined(); 

    // Simulate resolving of promise 
    deferred.resolve(123); 
    // Note that the 'then' function does not get called synchronously. 
    // This is because we want the promise API to always be async, whether or not 
    // it got called synchronously or asynchronously. 
    expect(resolvedValue).toBeUndefined(); 

    // Propagate promise resolution to 'then' functions using $apply(). 
    $rootScope.$apply(); 
    expect(resolvedValue).toEqual(123); 
})); 

नुकसान यह है कि अपने कोड कोणीय से जुड़ा हुआ है है, फायदे हैं जो आपके कोड फ्लैट है और यह 2.x के लिए + पोर्टेबल है!

मैं मोचा टेस्ट रनर का प्रशंसक था जिसने मुझे अपने परीक्षणों में वादे वापस करने की इजाजत दी, आप इसे पाने की कोशिश कर सकते थे, लेकिन इसके लिए डाउनसाइड्स भी हैं, विशेष रूप से एक परीक्षण के लिए अपने कोड को संशोधित करने की आवश्यकता है।

4

उम्मीद है कि यह समाधान मदद करता है। जब परीक्षण निर्भरता का मज़ाक उड़ा रहा है तो एक दृष्टिकोण मुझे उपयोगी पाया गया है। मैंने टिप्पणी करने की कोशिश की है कि मैंने जितना संभव हो उतना किया है।

var returnMock, $scope, TestServiceMock, controller; 

beforeEach(module('app')); 

beforeEach(inject(function($controller) { 
    returnMock = { 
     then: jasmine.createSpy(), 
    }; 
    $scope = {}; 
    // first assumption is You are testing TestService extensively, 
    // I don't care about what getData has to do to get results 
    // All I care about is it gets called when I call loadData 
    TestServiceMock = { 
     getData: jasmine.createSpy().and.returnValue(returnMock); 
    }; 

    controller = $controller; 
})); 

it('should load data when loadData function is called and result set is 
under 1000', function() { 
    controller('TestCtrl', { 
     $scope, 
     TestServiceMock 
    }); 
    // another assumption is your data comes back in such a format 
    // perhaps in the actual code check whether data exists and proceed 
    // or do some other action 
    var returnedData = { 
     data: [ 
      { 
       id: 1, 
       name: 'item 1', 
      }, 
     ] 
    } 
    // when I execute the function/method 
    $scope.loadData(); 
    // I expect getData to be called 
    expect(TestServiceMock.getData).toHaveBeenCalled(); 
    // I expect then to be called and the reason is I mocked it 
    expect(returnMock.then).toHaveBeenCalledWith(jasmine.any(Function)); 
    returnMock.then.calls.mostRecent().args[0](returnedData); 
    // expect data on scope to be equal to my mocked data 
    expect($scope.data).toEqual(returnedData.data); 
    // don't expect any result because 1 < 1000 
    expect($scope.filtered).toEqual([]); 
    expect($scope.filtered.length).toEqual(0); 
}); 

it('should load data when loadData function is called and result set is over 1000', 
    function() { 
    controller('TestCtrl', { 
     $scope, 
     TestServiceMock 
    }); 
    var returnedData = { 
     data: [ 
      { 
       id: 1, 
       name: 'item 1', 
      }, 
      { 
       id: 1000, 
       name: 'item 1000', 
      }, 
      { 
       id: 1001, 
       name: 'item 1000', 
      }, 
      { 
       id: 1002, 
       name: 'item 1002', 
      } 
     ] 
    } 
    $scope.loadData(); 
    expect(TestServiceMock.getData).toHaveBeenCalled(); 
    expect(returnMock.then).toHaveBeenCalledWith(jasmine.any(Function)); 
    returnMock.then.calls.mostRecent().args[0](returnedData); 
    expect($scope.data).toEqual(returnedData.data); 
    // expect a result because some entries in the mocked data have id > 1000 
    expect($scope.filtered).toEqual([ 
     { 
      id: 1001, 
      name: 'item 1000', 
     }, 
     { 
      id: 1002, 
      name: 'item 1002', 
     }]); 
    expect($scope.filtered.length).toEqual(2); 
}); 

Official Jasmine Docs अधिकतर अवधारणाओं को व्यापक रूप से समझाएं। उम्मीद है कि समाधान मदद करता है !!!!

+0

दृश्य के लिए कुछ वापस नहीं कर रहे हैं। इस उत्तर ने मेरे बेकन को बचाया। धन्यवाद! –

+1

यह मुझे यह जानकर प्रसन्न करता है कि आपके पास अभी भी आपका बेकन है :) @ क्रिसमोलिनारी – mahadjr

संबंधित मुद्दे