Tengo un servicio AngularJS escrito y me gustaría probarlo por unidad.
angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
factory('myService', function ($http, fooService, barService) {
this.something = function() {
// Do something with the injected services
};
return this;
});
Mi archivo app.js tiene estos registrados:
angular
.module('myApp', ['fooServiceProvider','barServiceProvider','myServiceProvider']
)
Puedo probar que el DI funciona como tal:
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();
});
});
Esto demostró que el servicio puede ser creado por el marco DI, sin embargo, a continuación quiero probar el servicio unitario, lo que significa simular los objetos inyectados.
¿Cómo voy a hacer esto?
Intenté poner mis objetos simulados en el módulo, por ejemplo
beforeEach(module(mockNavigationService));
y reescribiendo la definición de servicio como:
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); })
Pero esto último parece detener el servicio creado por la DI como todos.
¿Alguien sabe cómo puedo burlarme de los servicios inyectados para mis pruebas unitarias?
Gracias
David
javascript
angularjs
mocking
jasmine
angularjs-service
BanksySan
fuente
fuente
Respuestas:
Puede inyectar simulacros en su servicio usando
$provide
.Si tiene el siguiente servicio con una dependencia que tiene un método llamado getSomething:
Puede inyectar una versión simulada de myDependency de la siguiente manera:
Tenga en cuenta que debido a la llamada a
$provide.value
usted, en realidad no es necesario inyectar explícitamente myDependency en ningún lugar. Ocurre bajo el capó durante la inyección de myService. Al configurar mockDependency aquí, fácilmente podría ser un espía.Gracias a loyalBrown por el enlace a ese gran video .
fuente
beforeEach(module('myModule'));
llamada TIENE QUE llegar antes que labeforeEach(function () { MOCKING })
llamada, o de lo contrario los servicios reales sobrescribirán las simulaciones!$provide
llamada debe realizarse antes de usar$injector
, de lo contrario, recibirá un error:Injector already created, can not register a module!
Error: [ng:areq] Argument 'fn' is not a function, got Object
, asegúrese de poner unreturn
en la línea después$provide.value(...)
. Regresar implícitamente me$provide.value(...)
causó ese error.Desde mi punto de vista, no hay necesidad de burlarse de los servicios en sí. Simplemente burlarse de las funciones del servicio. De esa manera, puede hacer que angular inyecte sus servicios reales como lo hace en toda la aplicación. Luego, simule las funciones en el servicio según sea necesario usando la
spyOn
función de Jasmine .Ahora, si el servicio en sí es una función, y no un objeto con el que puede usar
spyOn
, hay otra forma de hacerlo. Necesitaba hacer esto y encontré algo que funciona bastante bien para mí. Consulte ¿Cómo se simula el servicio Angular que es una función?fuente
Otra opción para facilitar la simulación de dependencias en Angular y Jasmine es utilizar QuickMock. Se puede encontrar en GitHub y te permite crear simulacros simples de forma reutilizable. Puede clonarlo desde GitHub a través del siguiente enlace. El archivo README se explica por sí mismo, pero es de esperar que pueda ayudar a otros en el futuro.
https://github.com/tennisgent/QuickMock
Gestiona automáticamente todo el código repetitivo mencionado anteriormente, por lo que no tiene que escribir todo ese código de inyección simulado en cada prueba. Espero que ayude.
fuente
Además de la respuesta de John Galambos : si solo desea simular métodos específicos de un servicio, puede hacerlo así:
fuente
Si su controlador está escrito para tomar una dependencia como esta:
entonces puedes hacer una falsificación
someDependency
en una prueba de Jasmine como esta:fuente
Recientemente lancé ngImprovedTesting que debería facilitar las pruebas simuladas en AngularJS.
Para probar 'myService' (del módulo "myApp") con sus dependencias fooService y barService simuladas, puede hacer lo siguiente en su prueba Jasmine:
Para obtener más información sobre ngImprovedTesting, consulte su entrada de blog introductoria: http://blog.jdriven.com/2014/07/ng-improved-testing-mock-testing-for-angularjs-made-easy/
fuente
Sé que esta es una pregunta antigua, pero hay otra manera más fácil, puede crear un simulacro y deshabilitar el original inyectado en una función, se puede hacer usando spyOn en todos los métodos. ver código a continuación.
fuente