আমি জুঁইয়ের সাথে একটি কৌনিক জেএস পরিষেবাটি কীভাবে পরীক্ষা করব?


107

(এখানে একটি সম্পর্কিত প্রশ্ন রয়েছে: জেসমিন পরীক্ষা AngularJS মডিউলটি দেখতে পায় না )

আমি কেবল কৌনিক বুটস্ট্র্যাপিং ছাড়াই একটি পরিষেবা পরীক্ষা করতে চাই।

আমার কয়েকটি উদাহরণ এবং টিউটোরিয়াল আছে তবে আমি কোথাও যাচ্ছি না।

আমার কাছে মাত্র তিনটি ফাইল রয়েছে:

  • মাই সার্ভিস.জেএসস: যেখানে আমি একটি কৌনিক জেএস পরিষেবাটি সংজ্ঞায়িত করি

  • test_myService.js: যেখানে আমি পরিষেবাটির জন্য জেসমিন পরীক্ষাটি সংজ্ঞায়িত করি।

  • স্পেকআরনার এইচটিএমএল: সাধারণ জুঁই কনফিগারেশন সহ একটি এইচটিএমএল ফাইল এবং যেখানে আমি পূর্ববর্তী দুটি ফাইল এবং জেসমিন, অ্যাঙ্গুলারজ এবং কৌণিক-মকস.জেগুলি আমদানি করি।

এটি পরিষেবার জন্য কোড (যা আমি যখন পরীক্ষা না করি তখন প্রত্যাশা অনুযায়ী কাজ করে):

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

myModule.factory('myService', function(){

    var serviceImplementation   = {};
    serviceImplementation.one   = 1;
    serviceImplementation.two   = 2;
    serviceImplementation.three = 3;

    return serviceImplementation

});

আমি যেমন পরিষেবাটি বিচ্ছিন্নভাবে পরীক্ষা করার চেষ্টা করছি, আমার এটি অ্যাক্সেস করতে এবং তাদের পদ্ধতিগুলি পরীক্ষা করতে সক্ষম হওয়া উচিত। আমার প্রশ্ন: আমি কীভাবে AngularJS বুটস্ট্র্যাপিং না করে আমার পরীক্ষায় পরিষেবাটি ইনজেক্ট করতে পারি?

উদাহরণস্বরূপ, আমি কীভাবে জেসমিনের সাথে পরিষেবাটির কোনও পদ্ধতির জন্য প্রত্যাবর্তিত মানটি পরীক্ষা করতে পারি:

describe('myService test', function(){
    describe('when I call myService.one', function(){
        it('returns 1', function(){
            myModule = angular.module('myModule');
                    //something is missing here..
            expect( myService.one ).toEqual(1);
        })

    })

});

উত্তর:


137

সমস্যাটি হ'ল ফ্যাক্টরি পদ্ধতিটি, যা পরিষেবাটি ত্বরান্বিত করে, উপরের উদাহরণটিতে বলা হয় না (কেবলমাত্র মডিউল তৈরি করা পরিষেবাটি তাত্পর্যপূর্ণ করে না)।

পরিষেবাটি ইনস্ট্যান্টিয়েটেড করার জন্য কৌণিক.আইনজেক্টরকে আমাদের পরিষেবাটি সংজ্ঞায়িত এমন মডিউলটির সাথে কল করতে হবে। তারপরে, আমরা পরিষেবাটির জন্য নতুন ইনজেক্টর অবজেক্টটির কাছে জিজ্ঞাসা করতে পারি এবং এর পরে কেবল পরিষেবাটি তাত্ক্ষণিকভাবে চালু করা হয়।

এর মতো কিছু কাজ করে:

describe('myService test', function(){
    describe('when I call myService.one', function(){
        it('returns 1', function(){
            var $injector = angular.injector([ 'myModule' ]);
            var myService = $injector.get( 'myService' );
            expect( myService.one ).toEqual(1);
        })

    })

});

আর একটি উপায় হ'ল ' চালান ' ব্যবহার করে কোনও ফাংশনে পরিষেবাটি পৌঁছে দেওয়া :

describe('myService test', function(){
    describe('when I call myService.one', function(){
        it('returns 1', function(){

            myTestFunction = function(aService){
                expect( aService.one ).toEqual(1);
            }

            //we only need the following line if the name of the 
            //parameter in myTestFunction is not 'myService' or if
            //the code is going to be minify.
            myTestFunction.$inject = [ 'myService' ];

            var myInjector = angular.injector([ 'myModule' ]);
            myInjector.invoke( myTestFunction );
        })

    })

});

এবং অবশেষে, এটি করার 'যথাযথ ' উপায়টি হ'ল ' ইনজেকশন ' এবং ' মডিউল ' একটি ' পূর্ববর্তী প্রতিটি ' জুঁই ব্লকে ব্যবহার করে। এটি করার সময় আমাদের বুঝতে হবে যে 'ইনজেক্ট' ফাংশনটি স্ট্যান্ডার্ড অ্যাঙ্গুলারজস প্যাকেজে নয়, এনজিমক মডিউলে রয়েছে এবং এটি কেবল জুঁই দিয়ে কাজ করে।

describe('myService test', function(){
    describe('when I call myService.one', function(){
        beforeEach(module('myModule'));
        it('returns 1', inject(function(myService){ //parameter name = service name

            expect( myService.one ).toEqual(1);

        }))

    })

});

13
আপনার পরিষেবাটির নিজস্ব নির্ভরতা (উদাহরণস্বরূপ লগ) এর উদাহরণ দেখতে পছন্দ করবেন
রায় ট্রুইলোভ

2
দুঃখিত, আমি আসলে এরকম কিছু খুঁজছিলাম: stackoverflow.com/q/16565531/295797
রায় ট্রুইলোভ

1
beforeEachঅনেকের ক্ষেত্রে ... অনেকগুলি ... অনেকগুলি পরীক্ষার প্রয়োজনে পরিষেবাটি ইনজেক্ট করার কি কোনও ভাল উপায় আছে ? একটি ডেটা মডেল (পরিষেবা) পরীক্ষা করে এটি এক টন বৈশ্বিক চলক ধারণ করে। ধন্যবাদ, সি§
সিএসএস

2
আপনি (3) কেন 'যথাযথ উপায়' তা বলছেন না
লিগি

2
@ লিগি আমি মনে করি আমরা একে 'যথাযথ' উপায় বলতে পারি কারণ এটি এনজিমক অ্যাঙ্গুলারজেএস মডিউলটি ব্যবহার করেছে যা এটি বিশেষত পরীক্ষার উদ্দেশ্যে for
রবার্ট

5

যদিও উপরের উত্তরটি সম্ভবত ঠিক কাজ করে (আমি এটি চেষ্টা করি নি :)), আমার প্রায়শই চালানোর জন্য আরও অনেক বেশি পরীক্ষা করা হয় যাতে আমি নিজে টেস্টে ইনজেকশন না দিয়ে থাকি। আমি এগুলি () কে ব্লকগুলি বর্ণনা করার ক্ষেত্রে গ্রুপ করব এবং প্রতিটি ইনজেকশনটি ব্লক বর্ণনা করার আগে বা পূর্ববর্তী প্রতিটি () বা এর আগে সমস্ত () চালাবো।

রবার্ট এ ক্ষেত্রেও সঠিক যে তিনি বলেছেন যে পরীক্ষাগুলি পরিষেবা বা কারখানায় সচেতন করতে আপনাকে অবশ্যই কৌনিক $ ইনজেক্টর ব্যবহার করতে হবে। কৌনিকটি আপনার অ্যাপ্লিকেশনগুলিতেও এই ইনজেক্টরটি নিজেই ব্যবহার করে অ্যাপ্লিকেশনটি উপলভ্য কী তা জানাতে। যাইহোক, এটা একাধিক জায়গায় বলা যেতে পারে, এবং এটা বলা যেতে পারে পরোক্ষভাবে পরিবর্তে স্পষ্টভাবে। আপনি নীচে আমার উদাহরণ সুনির্দিষ্ট টেস্ট ফাইলটিতে লক্ষ্য করবেন, পূর্বের প্রতিটি () ব্লক পরীক্ষার ভিতরে নির্ধারিত জিনিসগুলি সরবরাহের জন্য ইনজেক্টরকে স্পষ্টভাবে কল করে।

জিনিসগুলিকে গোষ্ঠীভুক্ত করতে এবং ব্লকগুলি ব্যবহার করে ফিরে যাওয়া, এখানে একটি ছোট উদাহরণ। আমি একটি বিড়াল পরিষেবা তৈরি করছি এবং আমি এটি পরীক্ষা করতে চাই, সুতরাং পরিষেবাটি লেখার এবং পরীক্ষা করার জন্য আমার সহজ সেটআপটি দেখতে এই জাতীয় দেখাচ্ছে:

app.js

var catsApp = angular.module('catsApp', ['ngMockE2E']);

angular.module('catsApp.mocks', [])
.value('StaticCatsData', function() {
  return [{
    id: 1,
    title: "Commando",
    name: "Kitty MeowMeow",
    score: 123
  }, {
    id: 2,
    title: "Raw Deal",
    name: "Basketpaws",
    score: 17
  }, {
    id: 3,
    title: "Predator",
    name: "Noseboops",
    score: 184
  }];
});

catsApp.factory('LoggingService', ['$log', function($log) {

  // Private Helper: Object or String or what passed
    // for logging? Let's make it String-readable...
  function _parseStuffIntoMessage(stuff) {
    var message = "";
    if (typeof stuff !== "string") {
      message = JSON.stringify(stuff)
    } else {
      message = stuff;
    }

    return message;
  }

  /**
   * @summary
   * Write a log statement for debug or informational purposes.
   */
  var write = function(stuff) {
    var log_msg = _parseStuffIntoMessage(stuff);
    $log.log(log_msg);
  }

  /**
   * @summary
   * Write's an error out to the console.
   */
  var error = function(stuff) {
    var err_msg = _parseStuffIntoMessage(stuff);
    $log.error(err_msg);
  }

  return {
    error: error,
    write: write
  };

}])

catsApp.factory('CatsService', ['$http', 'LoggingService', function($http, Logging) {

  /*
    response:
      data, status, headers, config, statusText
  */
  var Success_Callback = function(response) {
    Logging.write("CatsService::getAllCats()::Success!");
    return {"status": status, "data": data};
  }

  var Error_Callback = function(response) {
    Logging.error("CatsService::getAllCats()::Error!");
    return {"status": status, "data": data};
  }

  var allCats = function() {
    console.log('# Cats.allCats()');
    return $http.get('/cats')
      .then(Success_Callback, Error_Callback);
  }

  return {
    getAllCats: allCats
  };

}]);

var CatsController = function(Cats, $scope) {

  var vm = this;

  vm.cats = [];

  // ========================

  /**
   * @summary
   * Initializes the controller.
   */
  vm.activate = function() {
    console.log('* CatsCtrl.activate()!');

    // Get ALL the cats!
    Cats.getAllCats().then(
      function(litter) {
        console.log('> ', litter);
        vm.cats = litter;
        console.log('>>> ', vm.cats);
      }  
    );
  }

  vm.activate();

}
CatsController.$inject = ['CatsService', '$scope'];
catsApp.controller('CatsCtrl', CatsController);

বৈশিষ্ট: বিড়াল নিয়ন্ত্রক

'use strict';

describe('Unit Tests: Cats Controller', function() {

    var $scope, $q, deferred, $controller, $rootScope, catsCtrl, mockCatsData, createCatsCtrl;

    beforeEach(module('catsApp'));
    beforeEach(module('catsApp.mocks'));

    var catsServiceMock;

    beforeEach(inject(function(_$q_, _$controller_, $injector, StaticCatsData) {
      $q = _$q_;
      $controller = _$controller_;

      deferred = $q.defer();

      mockCatsData = StaticCatsData();

      // ToDo:
        // Put catsServiceMock inside of module "catsApp.mocks" ?
      catsServiceMock = {
        getAllCats: function() {
          // Just give back the data we expect.
          deferred.resolve(mockCatsData);
          // Mock the Promise, too, so it can run
            // and call .then() as expected
          return deferred.promise;
        }
      };
    }));


    // Controller MOCK
    var createCatsController;
    // beforeEach(inject(function (_$rootScope_, $controller, FakeCatsService) {
    beforeEach(inject(function (_$rootScope_, $controller, CatsService) {

      $rootScope = _$rootScope_;

      $scope = $rootScope.$new();
      createCatsController = function() {
          return $controller('CatsCtrl', {
              '$scope': $scope,
              CatsService: catsServiceMock
          });    
      };
    }));

    // ==========================

    it('should have NO cats loaded at first', function() {
      catsCtrl = createCatsController();

      expect(catsCtrl.cats).toBeDefined();
      expect(catsCtrl.cats.length).toEqual(0);
    });

    it('should call "activate()" on load, but only once', function() {
      catsCtrl = createCatsController();
      spyOn(catsCtrl, 'activate').and.returnValue(mockCatsData);

      // *** For some reason, Auto-Executing init functions
      // aren't working for me in Plunkr?
      // I have to call it once manually instead of relying on
      // $scope creation to do it... Sorry, not sure why.
      catsCtrl.activate();
      $rootScope.$digest();   // ELSE ...then() does NOT resolve.

      expect(catsCtrl.activate).toBeDefined();
      expect(catsCtrl.activate).toHaveBeenCalled();
      expect(catsCtrl.activate.calls.count()).toEqual(1);

      // Test/Expect additional  conditions for 
        // "Yes, the controller was activated right!"
      // (A) - there is be cats
      expect(catsCtrl.cats.length).toBeGreaterThan(0);
    });

    // (B) - there is be cats SUCH THAT
      // can haz these properties...
    it('each cat will have a NAME, TITLE and SCORE', function() {
      catsCtrl = createCatsController();
      spyOn(catsCtrl, 'activate').and.returnValue(mockCatsData);

      // *** and again...
      catsCtrl.activate();
      $rootScope.$digest();   // ELSE ...then() does NOT resolve.

      var names = _.map(catsCtrl.cats, function(cat) { return cat.name; })
      var titles = _.map(catsCtrl.cats, function(cat) { return cat.title; })
      var scores = _.map(catsCtrl.cats, function(cat) { return cat.score; })

      expect(names.length).toEqual(3);
      expect(titles.length).toEqual(3);
      expect(scores.length).toEqual(3); 
    });

});

স্পেস: বিড়ালদের পরিষেবা

'use strict';

describe('Unit Tests: Cats Service', function() {

  var $scope, $rootScope, $log, cats, logging, $httpBackend, mockCatsData;

  beforeEach(module('catsApp'));
  beforeEach(module('catsApp.mocks'));

  describe('has a method: getAllCats() that', function() {

    beforeEach(inject(function($q, _$rootScope_, _$httpBackend_, _$log_, $injector, StaticCatsData) {
      cats = $injector.get('CatsService');
      $rootScope = _$rootScope_;
      $httpBackend = _$httpBackend_;

      // We don't want to test the resolving of *actual data*
      // in a unit test.
      // The "proper" place for that is in Integration Test, which
      // is basically a unit test that is less mocked - you test
      // the endpoints and responses and APIs instead of the
      // specific service behaviors.
      mockCatsData = StaticCatsData();

      // For handling Promises and deferrals in our Service calls...
      var deferred = $q.defer();
      deferred.resolve(mockCatsData); //  always resolved, you can do it from your spec

      // jasmine 2.0
        // Spy + Promise Mocking
        // spyOn(obj, 'method'), (assumes obj.method is a function)
      spyOn(cats, 'getAllCats').and.returnValue(deferred.promise);

      /*
        To mock $http as a dependency, use $httpBackend to
        setup HTTP calls and expectations.
      */
      $httpBackend.whenGET('/cats').respond(200, mockCatsData);
    }));

    afterEach(function() {
      $httpBackend.verifyNoOutstandingExpectation();
      $httpBackend.verifyNoOutstandingRequest();
    })

    it(' exists/is defined', function() {
      expect( cats.getAllCats ).toBeDefined();
      expect( typeof cats.getAllCats ).toEqual("function");
    });

    it(' returns an array of Cats, where each cat has a NAME, TITLE and SCORE', function() {
      cats.getAllCats().then(function(data) {
        var names = _.map(data, function(cat) { return cat.name; })
        var titles = _.map(data, function(cat) { return cat.title; })
        var scores = _.map(data, function(cat) { return cat.score; })

        expect(names.length).toEqual(3);
        expect(titles.length).toEqual(3);
        expect(scores.length).toEqual(3);
      })
    });

  })

  describe('has a method: getAllCats() that also logs', function() {

      var cats, $log, logging;

      beforeEach(inject(
        function(_$log_, $injector) {
          cats = $injector.get('CatsService');
          $log = _$log_;
          logging = $injector.get('LoggingService');

          spyOn(cats, 'getAllCats').and.callThrough();
        }
      ))

      it('that on SUCCESS, $logs to the console a success message', function() {
        cats.getAllCats().then(function(data) {
          expect(logging.write).toHaveBeenCalled();
          expect( $log.log.logs ).toContain(["CatsService::getAllCats()::Success!"]);
        })
      });

    })

});

সম্পাদনা কিছু মন্তব্যের উপর ভিত্তি করে, আমি আমার উত্তরটি আরও জটিল হতে আপডেট করেছি এবং আমি ইউনিট টেস্টিংয়ের জন্য একটি প্লাঙ্কারও তৈরি করেছি। বিশেষত, একটি মন্তব্যে উল্লেখ করা হয়েছে "যদি কোনও কন্ট্রোলারের পরিষেবাতে itself লগের মতো কোনও সাধারণ নির্ভরতা থাকে? - যা পরীক্ষার ক্ষেত্রে উদাহরণ সহ অন্তর্ভুক্ত। আশা করি এটা সাহায্য করবে! প্ল্যানেট পরীক্ষা বা হ্যাক করুন !!!

https://embed.plnkr.co/aSPHnr/


0

আমাকে এমন একটি নির্দেশ পরীক্ষা করার দরকার ছিল যার জন্য আরেকটি নির্দেশের দরকার ছিল, গুগল প্লেসস স্বতঃসম্পূর্ণ, আমি কেবল এটির উপহাস করব কিনা তা নিয়ে আমি বিতর্ক করছিলাম ... যাইহোক এটি জিপ্লেসস আউটোকম্পল্টের প্রয়োজনীয় নির্দেশের জন্য কোনও ত্রুটি ছুঁড়ে ফেলে কাজ করেছিল।

describe('Test directives:', function() {
    beforeEach(module(...));
    beforeEach(module(...));
    beforeEach(function() {
        angular.module('google.places', [])
        .directive('gPlacesAutocomplete',function() {
            return {
                require: ['ngModel'],
                restrict: 'A',
                scope:{},
                controller: function() { return {}; }
             };
        });
     });
     beforeEach(module('google.places'));
});

-5

আপনি যদি কোনও নিয়ামকের পরীক্ষা করতে চান তবে আপনি নীচের মতো এটি ইনজেকশন এবং পরীক্ষা করতে পারেন।

describe('When access Controller', function () {
    beforeEach(module('app'));

    var $controller;

    beforeEach(inject(function (_$controller_) {
        // The injector unwraps the underscores (_) from around the parameter names when matching
        $controller = _$controller_;
    }));

    describe('$scope.objectState', function () {
        it('is saying hello', function () {
            var $scope = {};
            var controller = $controller('yourController', { $scope: $scope });
            expect($scope.objectState).toEqual('hello');
        });
    });
});

2
প্রশ্ন পরীক্ষার পরিষেবা সম্পর্কে, নিয়ামক নয়।
বারটেক এস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.