Tenho um serviço AngularJS escrito e gostaria de fazer um teste de unidade.
angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
factory('myService', function ($http, fooService, barService) {
this.something = function() {
// Do something with the injected services
};
return this;
});
Meu arquivo app.js tem estes registrados:
angular
.module('myApp', ['fooServiceProvider','barServiceProvider','myServiceProvider']
)
Posso testar se o DI está funcionando da seguinte forma:
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();
});
});
Isso provou que o serviço pode ser criado pelo framework DI, porém agora quero fazer um teste de unidade do serviço, o que significa simular os objetos injetados.
Como faço para fazer isso?
Eu tentei colocar meus objetos fictícios no módulo, por exemplo
beforeEach(module(mockNavigationService));
e reescrevendo a definição de serviço 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); })
Mas o último parece impedir o serviço de ser criado pela DI como um todo.
Alguém sabe como posso simular os serviços injetados para meus testes de unidade?
obrigado
David
javascript
angularjs
mocking
jasmine
angularjs-service
BanksySan
fonte
fonte
Respostas:
Você pode injetar simulações em seu serviço usando
$provide
.Se você tiver o seguinte serviço com uma dependência que tem um método chamado getSomething:
Você pode injetar uma versão simulada de myDependency da seguinte maneira:
Observe que, por causa da chamada para
$provide.value
você, na verdade, você não precisa injetar explicitamente myDependency em qualquer lugar. Acontece sob o capô durante a injeção de myService. Ao configurar o mockDependency aqui, ele poderia facilmente ser um espião.Obrigado a loyalBrown pelo link para aquele ótimo vídeo .
fonte
beforeEach(module('myModule'));
chamada TEM que vir antes dabeforeEach(function () { MOCKING })
chamada, senão as simulações serão substituídas pelos serviços reais!$provide
chamadas devem ser feitas antes de usar$injector
, caso contrário, você receberá um erro:Injector already created, can not register a module!
Error: [ng:areq] Argument 'fn' is not a function, got Object
, certifique-se de colocar umreturn
na linha depois$provide.value(...)
. Voltar implicitamente$provide.value(...)
causou esse erro para mim.A meu ver, não há necessidade de zombar dos próprios serviços. Simplesmente simule as funções do serviço. Dessa forma, você pode fazer com que o angular injete seus serviços reais como faz em todo o aplicativo. Em seguida, simule as funções no serviço conforme necessário usando a
spyOn
função do Jasmine .Agora, se o serviço em si é uma função, e não um objeto com o qual você pode usar
spyOn
, há outra maneira de fazer isso. Eu precisava fazer isso e encontrei algo que funciona muito bem para mim. Consulte Como você simula o serviço Angular que é uma função?fonte
Outra opção para ajudar a tornar a simulação de dependências mais fácil no Angular e Jasmine é usar o QuickMock. Ele pode ser encontrado no GitHub e permite que você crie simulações simples de uma forma reutilizável. Você pode cloná-lo do GitHub por meio do link abaixo. O README é bastante autoexplicativo, mas espero que possa ajudar outras pessoas no futuro.
https://github.com/tennisgent/QuickMock
Ele gerencia automaticamente todo o boilerplate mencionado acima, então você não precisa escrever todo o código de injeção de simulação em cada teste. Espero que ajude.
fonte
Além da resposta de John Galambos : se você apenas quer zombar de métodos específicos de um serviço, pode fazer assim:
fonte
Se o seu controlador foi escrito para assumir uma dependência como esta:
então você pode fazer um falso
someDependency
em um teste Jasmine como este:fonte
Recentemente, lancei o ngImprovedTesting que deve tornar o teste de simulação em AngularJS mais fácil.
Para testar 'myService' (do módulo "myApp") com suas dependências fooService e barService simuladas, você pode fazer o seguinte em seu teste Jasmine:
Para obter mais informações sobre o ngImprovedTesting, confira sua postagem introdutória no blog: http://blog.jdriven.com/2014/07/ng-improved-testing-mock-testing-for-angularjs-made-easy/
fonte
Eu sei que essa é uma questão antiga, mas há outra maneira mais fácil, você pode criar mock e desabilitar o original injetado em uma função, isso pode ser feito usando spyOn em todos os métodos. veja o código abaixo.
fonte