javascript - Hvordan løser jeg et promise i en AngularJS enhedstest
Jeg bruger den grundlæggende karma/jasmine-opsætning til at teste min Angular-kode. Her er min test:
var $controllerConstructor, ctr, mockSuperheroData, scope, deferred, q;
describe('main controller', function() {
var $controllerConstructor, ctr, mockSuperheroData, scope, deferred, q;
beforeEach(inject(function($controller, $rootScope, $q) {
scope = $rootScope.$new();
$controllerConstructor = $controller;
q = $q;
mockSuperheroData = {
getSuperheroes: function() {
deferred = q.defer();
return deferred.promise;
}
};
ctr = $controllerConstructor('MainCtrl', {$scope: scope, $location: {}, superheroService: mockSuperheroData, keys: {}});
}));
it('should set the result of getResource to scope.heroes', function() {
scope.getHeroes();
expect(scope.heroes).toBe(100);
});
}
scope.getHeroes() kalder mockSuperheroData.getSuperheroes(), som returnerer et løfte (promise). Hvordan tvinger jeg løftet til at returnere det, jeg ønsker, i en enhedstest? Hvor kan jeg tilknytte mig løftet for at mocke dets returværdi?
Svar #1
Hvordan tvinger jeg løftet til at returnere det, jeg vil, i en enhedstest?
Grundlæggende skal du kalde resolve på Deferred:
deferred.resolve(100);
Du kan enten sætte det direkte før return deferred.promise eller i en asynkron setTimeout.
Svar #2
var $controllerConstructor, ctr, mockSuperheroData, scope, deferred, q;
describe('main controller', function() {
var $controllerConstructor, ctr, mockSuperheroData, scope, deferred, q, rootScope;
beforeEach(inject(function($controller, $rootScope, $q) {
scope = $rootScope.$new();
$controllerConstructor = $controller;
q = $q;
rootScope = $rootScope;
mockSuperheroData = {
getSuperheroes: function() {
deferred = q.defer();
return deferred.promise;
}
};
ctr = $controllerConstructor('MainCtrl', {$scope: scope, $location: {}, superheroService: mockSuperheroData, keys: {}});
}));
it('should set the result of getResource to scope.heroes', function() {
scope.getHeroes();
deferred.resolve(100);
rootScope.$apply();
expect(scope.heroes).toBe(100);
});
});
Det skal nævnes, at fordi $q er integreret med $rootScope, skal du ikke kun løse det udskudte objekt, men du skal også udbrede ændringerne ved at kalde $rootScope.$apply.
Jeg skrev en blog om at latterliggøre Angular-løfter på projectpoppycock
og jeg skrev et fungerende eksempel, med tests, på plunkr
Jeg kan virkelig godt lide den måde, du injicerer mock-tjenesten som en afhængighed af controlleren ved at bruge $controller-tjenesten, jeg må måske revidere min måde at gøre dette på. Din måde er bedre :) Tak!
