একটি কৌণিক জেএস পরিষেবাতে একটি মক ইনজেকশন


114

আমার একটি AngularJS পরিষেবা লিখিত আছে এবং আমি এটির ইউনিট পরীক্ষা করতে চাই।

angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
    factory('myService', function ($http, fooService, barService) {

    this.something = function() {
        // Do something with the injected services
    };

    return this;
});

আমার app.js ফাইলটিতে এইগুলি নিবন্ধিত রয়েছে:

angular
.module('myApp', ['fooServiceProvider','barServiceProvider','myServiceProvider']
)

আমি ডিআই পরীক্ষা করতে পারি যে এটি কাজ করছে:

describe("Using the DI framework", function() {
    beforeEach(module('fooServiceProvider'));
    beforeEach(module('barServiceProvider'));
    beforeEach(module('myServiceProvder'));

    var service;

    beforeEach(inject(function(fooService, barService, myService) {
        service=myService;
    }));

    it("can be instantiated", function() {
        expect(service).not.toBeNull();
    });
});

এটি প্রমাণ করে যে পরিষেবাটি ডিআই কাঠামোর দ্বারা তৈরি করা যেতে পারে, তবে এরপরে আমি পরিষেবাটি ইউনিট করতে চাই, যার অর্থ ইনজেকশনযুক্ত বস্তুগুলি উপহাস করা।

কিভাবে আমি এই কাজ সম্পর্কে যান?

আমি আমার মক জিনিসগুলি মডিউলে রাখার চেষ্টা করেছি, যেমন

beforeEach(module(mockNavigationService));

এবং পরিষেবা সংজ্ঞাটি আবার লিখতে হবে:

function MyService(http, fooService, barService) {
    this.somthing = function() {
        // Do something with the injected services
    };
});

angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
    factory('myService', function ($http, fooService, barService) { return new MyService($http, fooService, barService); })

তবে পরবর্তীকালে ডিআই দ্বারা তৈরি করা পরিষেবাটি সকলের মতো বন্ধ করে দেওয়া হবে বলে মনে হচ্ছে।

কেউ কি জানেন যে আমি কীভাবে আমার ইউনিট পরীক্ষার জন্য ইঞ্জেকশন করা পরিষেবাগুলি উপহাস করতে পারি?

ধন্যবাদ

ডেভিড


আমার এই প্রশ্নের উত্তরটি আপনি অন্য প্রশ্নের দিকে একবার দেখতে পারেন , আমি আশা করি এটি আপনার পক্ষে সহায়ক হতে পারে।
রিমিগিও

উত্তর:


183

আপনি ব্যবহার করে আপনার পরিষেবাতে মক ইনজেকশন করতে পারেন $provide

আপনার যদি নির্ভরতা সহ নিম্নলিখিত পরিষেবাটি থাকে যা একটি পদ্ধতি রয়েছে যার নাম গিটসামিং:

angular.module('myModule', [])
  .factory('myService', function (myDependency) {
        return {
            useDependency: function () {
                return myDependency.getSomething();
            }
        };
  });

আপনি নিম্নরূপে মাই ডিপেন্ডেন্সির একটি মক সংস্করণ ইনজেক্ট করতে পারেন:

describe('Service: myService', function () {

  var mockDependency;

  beforeEach(module('myModule'));

  beforeEach(function () {

      mockDependency = {
          getSomething: function () {
              return 'mockReturnValue';
          }
      };

      module(function ($provide) {
          $provide.value('myDependency', mockDependency);
      });

  });

  it('should return value from mock dependency', inject(function (myService) {
      expect(myService.useDependency()).toBe('mockReturnValue');
  }));

});

মনে রাখবেন যে $provide.valueআপনাকে কল করার কারণে প্রকৃতপক্ষে স্পষ্টভাবে কোথাও MyD dependency ইনজেক্ট করার দরকার নেই। এটি মাই সার্ভিসের ইনজেকশনের সময় হুডের নীচে ঘটে। এখানে মক ডিপেন্ডেনসি সেটআপ করার সময়, এটি ঠিক তত সহজে গুপ্তচর হতে পারে।

সেই দুর্দান্ত ভিডিওর লিঙ্কটির জন্য অনুগত ব্রাউনকে ধন্যবাদ ।


13
দুর্দান্ত কাজ, কিন্তু একটি বিস্তারিত সাবধান থেকো, beforeEach(module('myModule'));কল রয়েছে আগে অবশ্যই আসার চেষ্টা beforeEach(function () { MOCKING })কল, অথবা অন্য ঠাট্টা বাস্তব পরিসেবা দ্বারা ওভাররাইট পাবেন!
নিকস প্যারাস্কেভোপল্লোস

1
পরিষেবা উপহাস না করে একই পদ্ধতিতে অবিচল থাকার কি উপায় আছে?
আর্টেম

5
নিকোসের মন্তব্যের অনুরূপ, অন্যথায় $provideব্যবহারের আগে যে কোনও কল করতে হবে $injector, আপনি একটি ত্রুটি পাবেন:Injector already created, can not register a module!
প্রভিডেন্স্যাক

7
যদি আপনার মোককে $ কিউ প্রয়োজন হয়? তারপরে মোককে নিবন্ধ করার জন্য আপনি মডিউল () কল করার আগে মক মধ্যে into q ইনজেকশন করতে পারবেন না। কোন চিন্তা?
জেক

4
আপনি যদি কফিস্ক্রিপ্ট ব্যবহার করছেন এবং আপনি দেখতে পাচ্ছেন Error: [ng:areq] Argument 'fn' is not a function, got Object, returnপরে লাইনে একটি চাপিয়ে দেওয়ার বিষয়টি নিশ্চিত করুন $provide.value(...)। সুস্পষ্টভাবে ফিরে আসা $provide.value(...)আমার জন্য ত্রুটি ঘটায়।
yndolok

4

আমি এটি যেভাবে দেখছি, সেগুলি সেগুলি নিজেই উপহাস করার দরকার নেই। কেবল পরিষেবাতে ফাংশনগুলি উপহাস করুন। এইভাবে, আপনি অ্যাপ্লিকেশন জুড়ে যেমন আপনার আসল পরিষেবাগুলি কৌণিক ইনজেকশন করতে পারে। তারপরে, জেসমিনের spyOnফাংশনটি ব্যবহার করে পরিষেবাতে ফাংশনগুলি মক করুন ।

এখন, যদি পরিষেবাটি নিজেই কোনও ফাংশন হয় এবং আপনি যে অবজেক্টটি ব্যবহার করতে পারেন spyOnতা না হলে এটি চালিয়ে যাওয়ার আরও একটি উপায় আছে। আমার এটি করা দরকার ছিল এবং এমন একটি জিনিস খুঁজে পেয়েছি যা আমার পক্ষে বেশ ভালভাবে কাজ করে। দেখুন আপনি কীভাবে কৌনিক পরিষেবাটিকে একটি ফাংশনকে উপহাস করবেন?


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

1
যদি আপনি সার্ভারটি ডেটার জন্য হিট করার বিষয়ে উদ্বিগ্ন হন, তবে এটিই হ'ল ( ডকস.আঙ্গুলারজেএস.আর.ই.পি . / ম্যানগম্যাক.এইচটিটিপি ব্যাকএন্ড )। আমি নিশ্চিত নই যে পরিষেবাটির কারখানায় পুরো পরিষেবাটিকে মশকরা করা দরকার তার জন্য আর কী উদ্বেগের কারণ হবে।
dnc253

2

কৌণিক এবং জেসমিনে উপহাস নির্ভরতা আরও সহজ করার জন্য আরেকটি বিকল্প হ'ল কুইকমক ব্যবহার করা। এটি গিটহাবের সন্ধানে পাওয়া যায় এবং আপনাকে পুনরায় ব্যবহারযোগ্য উপায়ে সহজ উপহাস তৈরি করতে দেয়। আপনি নীচের লিঙ্কটি দিয়ে গিটহাব থেকে এটি ক্লোন করতে পারেন। README বেশ স্ব-বর্ণনামূলক, তবে আশা করি এটি ভবিষ্যতে অন্যদের সহায়তা করতে পারে।

https://github.com/tennisgent/QuickMock

describe('NotificationService', function () {
    var notificationService;

    beforeEach(function(){
        notificationService = QuickMock({
            providerName: 'NotificationService', // the provider we wish to test
            moduleName: 'QuickMockDemo',         // the module that contains our provider
            mockModules: ['QuickMockDemoMocks']  // module(s) that contains mocks for our provider's dependencies
        });
    });
    ....

এটি উপরে উল্লিখিত সমস্ত বয়লারপ্লেট স্বয়ংক্রিয়ভাবে পরিচালনা করে, তাই আপনাকে প্রতিটি পরীক্ষায় সেই মক ইনজেকশন কোডটি লিখতে হবে না। আশা করি এইটি কাজ করবে.


2

জন গ্যালাম্বোসের জবাব ছাড়াও : আপনি যদি কেবল কোনও পরিষেবার নির্দিষ্ট পদ্ধতিগুলি উপহাস করতে চান তবে আপনি এটি এটি করতে পারেন:

describe('Service: myService', function () {

  var mockDependency;

  beforeEach(module('myModule'));

  beforeEach(module(function ($provide, myDependencyProvider) {
      // Get an instance of the real service, then modify specific functions
      mockDependency = myDependencyProvider.$get();
      mockDependency.getSomething = function() { return 'mockReturnValue'; };
      $provide.value('myDependency', mockDependency);
  });

  it('should return value from mock dependency', inject(function (myService) {
      expect(myService.useDependency()).toBe('mockReturnValue');
  }));

});

1

আপনার নিয়ামক যদি এটির মতো নির্ভরতা নিতে লেখা হয়:

app.controller("SomeController", ["$scope", "someDependency", function ($scope, someDependency) {
    someDependency.someFunction();
}]);

তারপরে আপনি someDependencyজেসমিন পরীক্ষায় জাল তৈরি করতে পারেন :

describe("Some Controller", function () {

    beforeEach(module("app"));


    it("should call someMethod on someDependency", inject(function ($rootScope, $controller) {
        // make a fake SomeDependency object
        var someDependency = {
            someFunction: function () { }
        };

        spyOn(someDependency, "someFunction");

        // this instantiates SomeController, using the passed in object to resolve dependencies
        controller("SomeController", { $scope: scope, someDependency: someDependency });

        expect(someDependency.someFunction).toHaveBeenCalled();
    }));
});

9
প্রশ্ন পরিষেবাগুলির বিষয়ে, যা su নিয়ামক হিসাবে কোনও সমতুল্য পরিষেবায় কল দিয়ে পরীক্ষার স্যুটটিতে তাত্ক্ষণিকভাবে আসে না। অন্য কথায়, নির্ভরতা পাস করে, পূর্বের প্রতিটি ব্লকে পরিষেবা () কল করা হয় না।
মরিস সিঙ্গার

1

আমি সম্প্রতি এনজিআইপ্রোভেড টেস্টিং প্রকাশ করেছি যাতে অ্যাংুলারজেএস উপায়ে মক টেস্টি করা সহজ হয়।

'মাই সার্ভিস' ("মাই অ্যাপ্লিকেশন" মডিউল থেকে) এর ফস সার্ভিস এবং বার সার্ভিস নির্ভরতার সাথে পরীক্ষা করার জন্য আপনার জেসমিন পরীক্ষায় নিম্নলিখিতগুলি করতে পারেন:

beforeEach(ModuleBuilder
    .forModule('myApp')
    .serviceWithMocksFor('myService', 'fooService', 'barService')
    .build());

NgImprovedTesting সম্পর্কে আরও তথ্যের জন্য তার পরিচায়ক ব্লগ পোস্ট চেক আউট: http://blog.jdriven.com/2014/07/ng-improved-testing-mock-testing-for-angularjs-made-easy/


1
কেন এই নিচে ভোট হয়েছে? কোনও মন্তব্য ছাড়াই ডাউন-ভোটিংয়ের মানটি আমি বুঝতে পারি না।
জ্যাকব ব্রুয়ার

0

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

var mockInjectedProvider;

    beforeEach(function () {
        module('myModule');
    });

    beforeEach(inject(function (_injected_) { 
      mockInjectedProvider  = mock(_injected_);
    });

    beforeEach(inject(function (_base_) {
        baseProvider = _base_;
    }));

    it("injectedProvider should be mocked", function () {
    mockInjectedProvider.myFunc.andReturn('testvalue');    
    var resultFromMockedProvider = baseProvider.executeMyFuncFromInjected();
        expect(resultFromMockedProvider).toEqual('testvalue');
    }); 

    //mock all service methods
    function mock(angularServiceToMock) {

     for (var i = 0; i < Object.getOwnPropertyNames(angularServiceToMock).length; i++) {
      spyOn(angularServiceToMock,Object.getOwnPropertyNames(angularServiceToMock)[i]);
     }
                return angularServiceToMock;
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.