unit testingAngularJS服务时注入依赖服务
我正在testing服务A,但是服务A取决于服务B(即服务B被注入服务A)。
我已经看到了这个问题,但我的情况有点不同,因为在我看来, 嘲笑服务B而不是注入服务B的实际实例更有意义。我会用茉莉间谍来嘲笑它。
这是一个示例testing:
describe("Sample Test Suite", function() { beforeEach(function() { module('moduleThatContainsServiceA'); inject([ 'serviceA', function(service) { this.service = service; } ]); }); it('can create an instance of the service', function() { expect(this.service).toBeDefined(); }); });
我得到的错误是:
错误:未知提供者:serviceBProvider
我怎么能这样做?
其实在AngularJSdependency injection使用“最后的胜利”规则。 因此,您可以在包含模块和依赖关系之后,在testing中定义您的服务,然后当testing的服务A将使用DI请求服务B时,AngularJS将提供服务B的模拟版本。
这通常是通过定义像MyAppMocks这样的新模块,将模拟的服务/值放在那里,然后添加这个模块作为依赖。
(示意性):
beforeEach(function() { angular.module('MyAppMocks',[]).service('B', ...)); angular.module('Test',['MyApp','MyAppMocks']); ...
我在CoffeeScript中做了这个,发现了一个额外的问题。 (另外,我发现这个页面上的代码是混乱的简洁。)下面是一个完整的工作示例:
describe 'serviceA', -> mockServiceB = {} beforeEach module 'myApp' # (or just 'myApp.services') beforeEach -> angular.mock.module ($provide) -> $provide.value 'serviceB', mockServiceB null serviceA = null beforeEach inject ($injector) -> serviceA = $injector.get 'serviceA' it 'should work', -> expect( true ).toBe( true ) #serviceA.doStuff()
在$provide.value
后面没有显式地返回null,我不断收到Error: Argument 'fn' is not a function, got Object
。 我在这个Google网上论坛线程中find了答案。
Valentyn的解决scheme为我工作,但还有另一种select。
beforeEach(function () { angular.mock.module("moduleThatContainsServiceA", function ($provide) { $provide.value('B', ...); }); });
然后,当AngularJS服务A通过dependency injection请求服务B时,将提供服务B的模拟而不是来自moduleThatContainsServiceA的服务B.
这样你就不需要创build一个额外的angular度模块来模拟一个服务。
我发现最简单的方法就是注入服务B并模拟它。 例如服务车取决于服务引擎。 现在我们在testing汽车时需要模拟引擎:
describe('Testing a car', function() { var testEngine; beforeEach(module('plunker')); beforeEach(inject(function(engine){ testEngine = engine; })); it('should drive slow with a slow engine', inject(function(car) { spyOn(testEngine, 'speed').andReturn('slow'); expect(car.drive()).toEqual('Driving: slow'); })); });
参考: https : //github.com/angular/angular.js/issues/1635
这是为我工作。 关键是定义一个真正的模块被嘲笑。 调用angular.mock.module使真实模块可以嘲笑,并允许连接。
beforeEach( -> @weather_service_url = '/weather_service_url' @weather_provider_url = '/weather_provider_url' @weather_provider_image = "test.jpeg" @http_ret = 'http_works' module = angular.module('mockModule',[]) module.value('weather_service_url', @weather_service_url) module.value('weather_provider_url', @weather_provider_url) module.value('weather_provider_image', @weather_provider_image) module.service('weather_bug_service', services.WeatherBugService) angular.mock.module('mockModule') inject( ($httpBackend,weather_bug_service) => @$httpBackend = $httpBackend @$httpBackend.when('GET', @weather_service_url).respond(@http_ret) @subject = weather_bug_service ) )