into injection example entre diferencia dependency javascript unit-testing angularjs jasmine karma-runner

javascript - injection - inject controller into controller angularjs



Inyectar servicios dependientes cuando se prueban unidades AngularJS services (5)

De hecho, en AngularJS Dependency Injection usa la regla de "últimos triunfos". Entonces puede definir su servicio en su prueba justo después de incluir su módulo y sus dependencias, y luego, cuando el servicio A que está probando solicitará el servicio B usando DI, AngularJS dará una versión burlada del servicio B.

Esto a menudo se hace definiendo un nuevo módulo como MyAppMocks, colocando servicios / valores burlados allí y luego agregando este módulo como dependencia.

Tipo de (esquemáticamente):

beforeEach(function() { angular.module(''MyAppMocks'',[]).service(''B'', ...)); angular.module(''Test'',[''MyApp'',''MyAppMocks'']); ...

Estoy probando el servicio A, pero el servicio A depende del servicio B (es decir, el servicio B se inyecta en el servicio A).

He visto esta pregunta, pero mi caso es un poco diferente porque, en mi opinión, tiene más sentido burlarse del servicio B en lugar de inyectar una instancia real del servicio B. Me burlaría de él con un espía de jazmín.

Aquí hay una prueba de muestra:

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(); }); });

El error que recibo es:

Error: proveedor desconocido: serviceBProvider

¿Cómo podría hacer algo como esto?


Encuentro que el método más simple es simplemente inyectar el servicio B y simularlo. por ejemplo, el automóvil de servicio depende del motor de servicio. Ahora tenemos que simular el motor al probar el coche:

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''); })); });

Referencia: https://github.com/angular/angular.js/issues/1635


Estaba haciendo esto en CoffeeScript y encontré un gotcha extra. (Además, encontré que el código en esta página es confuso y escueto.) Aquí hay un ejemplo completo de trabajo:

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()

Sin devolver explícitamente null después de $provide.value , seguí obteniendo Error: Argument ''fn'' is not a function, got Object $provide.value Error: Argument ''fn'' is not a function, got Object . Encontré la respuesta en este hilo de Grupos de Google .


Esto es lo que funcionó para mí. La clave es definir un módulo real para burlarse. Llamar a angular.mock.module hace que el módulo real se pueda burlar y permite que las cosas se conecten.

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 ) )


La solución Valentyn funcionó para mí, pero hay otra alternativa.

beforeEach(function () { angular.mock.module("moduleThatContainsServiceA", function ($provide) { $provide.value(''B'', ...); }); });

Luego, cuando el servicio A de AngularJS solicite el Servicio B mediante Inyección de Dependencia, se proporcionará su simulacro de Servicio B en lugar del Servicio B del móduloThatContainsServiceA.

De esta forma, no es necesario crear un módulo angular adicional solo para simular un servicio.