Mam napisaną usługę AngularJS i chciałbym ją przetestować.
angular.module('myServiceProvider', ['fooServiceProvider', 'barServiceProvider']).
factory('myService', function ($http, fooService, barService) {
this.something = function() {
// Do something with the injected services
};
return this;
});
Mój plik app.js zawiera te zarejestrowane:
angular
.module('myApp', ['fooServiceProvider','barServiceProvider','myServiceProvider']
)
Mogę sprawdzić, czy DI działa jako takie:
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();
});
});
Udowodniło to, że usługa może być utworzona przez framework DI, jednak następnie chcę przeprowadzić testy jednostkowe usługi, co oznacza mockowanie wstrzykniętych obiektów.
Jak mam to zrobić?
Próbowałem umieścić w module moje pozorowane obiekty np
beforeEach(module(mockNavigationService));
i przepisanie definicji usługi jako:
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); })
Ale to drugie wydaje się powstrzymywać tworzenie usługi przez DI jak wszystko.
Czy ktoś wie, jak mogę wyszydzać wstrzyknięte usługi dla moich testów jednostkowych?
Dzięki
David
javascript
angularjs
mocking
jasmine
angularjs-service
BanksySan
źródło
źródło
Odpowiedzi:
Możesz wstrzyknąć makiety do swojej usługi za pomocą
$provide
.Jeśli masz następującą usługę z zależnością, która ma metodę o nazwie getSomething:
Możesz wstrzyknąć pozorowaną wersję myDependency w następujący sposób:
Zauważ, że ze względu na wezwanie do
$provide.value
ciebie nie musisz nigdzie jawnie wstrzykiwać myDependency. Dzieje się to pod maską podczas wstrzykiwania myService. Konfigurując tutaj mockDependency, równie łatwo może być szpiegiem.Dzięki loyalBrown za link do tego świetnego filmu .
źródło
beforeEach(module('myModule'));
połączenie MUSI nastąpić przedbeforeEach(function () { MOCKING })
połączeniem, w przeciwnym razie makiety zostaną nadpisane przez prawdziwe usługi!$provide
przed użyciem należy wykonać wszystkie połączenia$injector
, w przeciwnym razie pojawi się błąd:Injector already created, can not register a module!
Error: [ng:areq] Argument 'fn' is not a function, got Object
, pamiętaj, aby wstawić znakreturn
po$provide.value(...)
. Niejawny powrót$provide.value(...)
spowodował ten błąd.Patrząc na to, nie ma potrzeby kpić z samych usług. Po prostu mock funkcje w usłudze. W ten sposób możesz mieć Angular wstrzykiwać swoje prawdziwe usługi, tak jak ma to miejsce w całej aplikacji. Następnie mock funkcje w usłudze w razie potrzeby, używając
spyOn
funkcji Jasmine .Teraz, jeśli sama usługa jest funkcją, a nie obiektem, z którym można korzystać, można to zrobić
spyOn
w inny sposób. Musiałem to zrobić i znalazłem coś, co działa całkiem dobrze. Zobacz Jak kpisz z usługi Angular, która jest funkcją?źródło
Inną opcją ułatwiającą mockowanie zależności w Angular i Jasmine jest użycie QuickMock. Można go znaleźć na GitHub i umożliwia tworzenie prostych makiet w sposób wielokrotnego użytku. Możesz sklonować go z GitHub za pomocą poniższego linku. README jest dość zrozumiały, ale miejmy nadzieję, że może pomóc innym w przyszłości.
https://github.com/tennisgent/QuickMock
Automatycznie zarządza wszystkimi wymienionymi powyżej wzorcami, więc nie musisz pisać całego tego próbnego kodu wtrysku w każdym teście. Mam nadzieję, że to pomoże.
źródło
Oprócz odpowiedzi Johna Galambosa : jeśli chcesz po prostu wyszydzić określone metody usługi, możesz to zrobić w ten sposób:
źródło
Jeśli twój kontroler jest napisany tak, aby przyjmował taką zależność:
wtedy możesz zrobić fałszywkę
someDependency
w teście Jasmine w następujący sposób:źródło
Niedawno wydałem ngImprovedTesting, które powinno znacznie ułatwić testowanie próbne w AngularJS.
Aby przetestować 'myService' (z modułu "myApp") z jego zależnościami fooService i barService, możesz w prosty sposób wykonać następujące czynności w swoim teście Jasmine:
Aby uzyskać więcej informacji na temat ngImprovedTesting, zapoznaj się z wprowadzającym wpisem na blogu: http://blog.jdriven.com/2014/07/ng-improved-testing-mock-testing-for-angularjs-made-easy/
źródło
Wiem, że to stare pytanie, ale jest inny łatwiejszy sposób, możesz utworzyć próbę i wyłączyć oryginalny wstrzyknięty w jednej funkcji, można to zrobić za pomocą spyOn na wszystkich metodach. zobacz kod poniżej.
źródło