2013-02-08 35 views
50

Có ai có ví dụ về cách đơn vị kiểm tra nhà cung cấp không?Cách kiểm tra nhà cung cấp tùy chỉnh AngularJS

Ví dụ:

config.js

angular.module('app.config', []) 
    .provider('config', function() { 
    var config = { 
      mode: 'distributed', 
      api: 'path/to/api' 
     }; 

    this.mode = function (type) { 
     if (type) { 
     config.isDistributedInstance = type === config.mode; 
     config.isLocalInstance = !config.isDistributedInstance; 
     config.mode = type; 
     return this; 
     } else { 
     return config.mode; 
     } 
    }; 

    this.$get = function() { 
     return config; 
    }; 
    }]); 

app.js

angular.module('app', ['app.config']) 
    .config(['configProvider', function (configProvider) { 
    configProvider.mode('local'); 
    }]); 

app.js là sử dụng trong các thử nghiệm và tôi thấy đã được cấu hình configProvider và tôi có thể kiểm tra nó như một dịch vụ. Nhưng làm thế nào tôi có thể kiểm tra khả năng cấu hình? Hay nó không cần chút nào?

Trả lời

63

Tôi đã có cùng một câu hỏi này và chỉ tìm thấy giải pháp làm việc trong số Google Group answer và được tham chiếu fiddle example.

kiểm tra mã nhà cung cấp của bạn sẽ trông như thế này (sau mã trong fiddle example và những gì làm việc cho tôi):

describe('Test app.config provider', function() { 

    var theConfigProvider; 

    beforeEach(function() { 
     // Initialize the service provider 
     // by injecting it to a fake module's config block 
     var fakeModule = angular.module('test.app.config', function() {}); 
     fakeModule.config(function (configProvider) { 
      theConfigProvider = configProvider; 
     }); 
     // Initialize test.app injector 
     module('app.config', 'test.app.config'); 

     // Kickstart the injectors previously registered 
     // with calls to angular.mock.module 
     inject(function() {}); 
    }); 

    describe('with custom configuration', function() { 
     it('tests the providers internal function', function() { 
      // check sanity 
      expect(theConfigProvider).not.toBeUndefined(); 
      // configure the provider 
      theConfigProvider.mode('local'); 
      // test an instance of the provider for 
      // the custom configuration changes 
      expect(theConfigProvider.$get().mode).toBe('local'); 
     }); 
    }); 

}); 
+0

cảm ơn bạn đã đăng bài này! Tôi đã làm theo hướng dẫn được tìm thấy ở đây và không thành công: https://github.com/angular/angular.js/issues/2274. Ví dụ ở trên hoạt động như mong đợi. Cảm ơn! – zayquan

+0

Khi làm điều này, tôi phải thay đổi khai báo của mô-đun giả để truyền vào một mảng trống thay vì một hàm trống. Có thể do phiên bản mới hơn của Angular. –

45

tôi đã sử dụng giải pháp @ Mark Gemmill và nó hoạt động tốt, nhưng sau đó stumbled qua giải pháp tiết kiệm hơn một chút này, loại bỏ sự cần thiết cho một mô-đun giả mạo.

https://stackoverflow.com/a/15828369/1798234

Vì vậy,

var provider; 

beforeEach(module('app.config', function(theConfigProvider) { 
    provider = theConfigProvider; 
})) 

it('tests the providers internal function', inject(function() { 
    provider.mode('local') 
    expect(provider.$get().mode).toBe('local'); 
})); 


Nếu nhà cung cấp $ get phương pháp của bạn có phụ thuộc, bạn có thể vượt qua họ trong tay,

var provider; 

beforeEach(module('app.config', function(theConfigProvider) { 
    provider = theConfigProvider; 
})) 

it('tests the providers internal function', inject(function(dependency1, dependency2) { 
    provider.mode('local') 
    expect(provider.$get(dependency1, dependency2).mode).toBe('local'); 
})); 


Hoặc sử dụng $ vòi phun để tạo một phiên bản mới,

var provider; 

beforeEach(module('app.config', function(theConfigProvider) { 
    provider = theConfigProvider; 
})) 

it('tests the providers internal function', inject(function($injector) { 
    provider.mode('local') 
    var service = $injector.invoke(provider); 
    expect(service.mode).toBe('local'); 
})); 


Cả hai bên trên cũng sẽ cho phép bạn cấu hình lại các nhà cung cấp cho mỗi cá nhân it tuyên bố trong một khối describe. Nhưng nếu bạn chỉ cần cấu hình cung cấp một lần cho nhiều bài kiểm tra, bạn có thể làm điều này,

var service; 

beforeEach(module('app.config', function(theConfigProvider) { 
    var provider = theConfigProvider; 
    provider.mode('local'); 
})) 

beforeEach(inject(function(theConfig){ 
    service = theConfig; 
})); 

it('tests the providers internal function', function() { 
    expect(service.mode).toBe('local'); 
}); 

it('tests something else on service', function() { 
    ... 
}); 
2

đây là một helper nhỏ mà đúng gói gọn các nhà cung cấp quyến rũ, do đó đảm bảo cách ly giữa các xét nghiệm cá nhân:

/** 
    * @description request a provider by name. 
    * IMPORTANT NOTE: 
    * 1) this function must be called before any calls to 'inject', 
    * because it itself calls 'module'. 
    * 2) the returned function must be called after any calls to 'module', 
    * because it itself calls 'inject'. 
    * @param {string} moduleName 
    * @param {string} providerName 
    * @returns {function} that returns the requested provider by calling 'inject' 
    * usage examples: 
    it('fetches a Provider in a "module" step and an "inject" step', 
     function() { 
     // 'module' step, no calls to 'inject' before this 
     var getProvider = 
     providerGetter('module.containing.provider', 'RequestedProvider'); 
     // 'inject' step, no calls to 'module' after this 
     var requestedProvider = getProvider(); 
     // done! 
     expect(requestedProvider.$get).toBeDefined(); 
    }); 
    * 
    it('also fetches a Provider in a single step', function() { 
     var requestedProvider = 
     providerGetter('module.containing.provider', 'RequestedProvider')(); 

     expect(requestedProvider.$get).toBeDefined(); 
    }); 
    */ 
    function providerGetter(moduleName, providerName) { 
    var provider; 
    module(moduleName, 
      [providerName, function(Provider) { provider = Provider; }]); 
    return function() { inject(); return provider; }; // inject calls the above 
    } 
  • quy trình tìm nạp nhà cung cấp được đóng gói hoàn toàn: không cần biến đóng để giảm sự cách ly giữa các lần kiểm tra.
  • quy trình có thể được chia thành hai bước, bước 'mô-đun' và bước 'tiêm', có thể được nhóm tương ứng với các cuộc gọi khác thành 'mô-đun' và 'tiêm' trong thử nghiệm đơn vị.
  • nếu không cần chia nhỏ, việc truy xuất nhà cung cấp có thể được thực hiện đơn giản chỉ bằng một lệnh!
3

@Stephane Câu trả lời của Catala đặc biệt hữu ích và tôi đã sử dụng nhà cung cấp của anh ấy để có được chính xác những gì tôi muốn. Việc có thể yêu cầu nhà cung cấp thực hiện khởi tạo và sau đó là dịch vụ thực tế để xác thực rằng mọi thứ đang hoạt động chính xác với các cài đặt khác nhau là quan trọng. mã ví dụ:

angular 
     .module('test', []) 
     .provider('info', info); 

    function info() { 
     var nfo = 'nothing'; 
     this.setInfo = function setInfo(s) { nfo = s; }; 
     this.$get = Info; 

     function Info() { 
      return { getInfo: function() {return nfo;} }; 
     } 
    } 

The Jasmine kiểm tra spec:

describe("provider test", function() { 

     var infoProvider, info; 

     function providerGetter(moduleName, providerName) { 
      var provider; 
      module(moduleName, 
         [providerName, function(Provider) { provider = Provider; }]); 
      return function() { inject(); return provider; }; // inject calls the above 
     } 

     beforeEach(function() { 
      infoProvider = providerGetter('test', 'infoProvider')(); 
     }); 

     it('should return nothing if not set', function() { 
      inject(function(_info_) { info = _info_; }); 
      expect(info.getInfo()).toEqual('nothing'); 
     }); 

     it('should return the info that was set', function() { 
      infoProvider.setInfo('something'); 
      inject(function(_info_) { info = _info_; }); 
      expect(info.getInfo()).toEqual('something'); 
     }); 

    }); 
+0

Những người khác có thể xóa câu trả lời của họ bất kỳ lúc nào. Vì vậy, câu trả lời của bạn không nên đề cập đến bất kỳ câu trả lời nào khác. – manetsus

+2

chỉ cố gắng cung cấp tín dụng khi tín dụng đến hạn. Câu trả lời của tôi đã hoàn thành mà không có câu trả lời trước, mặc dù nó đi sâu hơn vào providerGetter - nhưng tôi mất một thời gian để tìm ra cách kiểm tra cả pha cung cấp và pha dịch vụ (như quan trọng đối với tình huống thực của tôi) nghĩ rằng tôi sẽ quăng nó vào đây - không có câu trả lời nào khác để kiểm tra cả thiết lập và sử dụng. – ScottG

+0

Điều đó tốt nhưng tín dụng sẽ chuyển đến nơi tín dụng. Trong trường hợp này, Nơi tín dụng sẽ bỏ phiếu nếu bạn có quyền bỏ phiếu. nếu không, hãy đợi cơ hội bỏ phiếu. Câu trả lời của bạn có thể là câu trả lời hay hơn, nhưng đó không phải là chủ đề của tôi (khi tôi tham gia vào đây để xem lại câu hỏi của bạn) và đó không phải là nơi thích hợp để trả tiền cho câu trả lời khác. Để biết thêm thông tin, hãy tham gia meta SO và biết thêm về tiêu chuẩn cộng đồng. @ScottG – manetsus

1

Cá nhân tôi sử dụng kỹ thuật này để chế giễu các nhà cung cấp đến từ thư viện bên ngoài, mà bạn có thể đặt trong một file helper cho tất cả các bài kiểm tra của bạn. Nó cũng có thể làm việc cho một nhà cung cấp tùy chỉnh như trong câu hỏi này tất nhiên. Ý tưởng là để xác định lại các nhà cung cấp trong mô-đun của mình trước khi nó được gọi bởi các ứng dụng

describe('app', function() { 
    beforeEach(module('app.config', function($provide) { 
    $provide.provider('config', function() { 
     var mode = jasmine.createSpy('config.mode'); 

     this.mode = mode; 

     this.$get = function() { 
     return { 
      mode: mode 
     }; 
     }; 
    }); 
    })); 

    beforeEach(module('app')); 

    describe('.config', function() { 
    it('should call config.mode', inject(function(config) { 
     expect(config.mode).toHaveBeenCalled(); 
    })); 
    }); 
}); 
1

Tôi chỉ cần thiết để kiểm tra rằng một số cài đặt đã được thiết lập một cách chính xác vào nhà cung cấp, vì vậy tôi sử dụng góc DI để cấu hình các nhà cung cấp khi Tôi đã khởi tạo mô-đun qua module().

Tôi cũng có một số vấn đề với nhà cung cấp không được tìm thấy, sau khi thử một số giải pháp ở trên, để nhấn mạnh sự cần thiết của một phương pháp thay thế.

Sau đó, tôi đã thêm các kiểm tra khác sử dụng cài đặt để kiểm tra xem chúng có phản ánh việc sử dụng giá trị cài đặt mới hay không.

describe("Service: My Service Provider", function() { 
    var myService, 
     DEFAULT_SETTING = 100, 
     NEW_DEFAULT_SETTING = 500; 

    beforeEach(function() { 

     function configurationFn(myServiceProvider) { 
      /* In this case, `myServiceProvider.defaultSetting` is an ES5 
      * property with only a getter. I have functions to explicitly 
      * set the property values. 
      */ 
      expect(myServiceProvider.defaultSetting).to.equal(DEFAULT_SETTING); 

      myServiceProvider.setDefaultSetting(NEW_DEFAULT_SETTING); 

      expect(myServiceProvider.defaultSetting).to.equal(NEW_DEFAULT_SETTING); 
     } 

     module("app", [ 
      "app.MyServiceProvider", 
      configurationFn 
     ]); 

     function injectionFn(_myService) { 
      myService = _myService; 
     } 

     inject(["app.MyService", injectionFn]); 
    }); 

    describe("#getMyDefaultSetting", function() { 

     it("should test the new setting", function() { 
      var result = myService.getMyDefaultSetting(); 

      expect(result).to.equal(NEW_DEFAULT_SETTING); 
     }); 

    }); 

}); 
Các vấn đề liên quan