2015-12-08 7 views
1

Итак, у меня есть это простое, орошенное приложение, которое возвращает алфавит НАТО, а затем выполняет юнит-тесты на нем, используя издевательства и обещания.AngularJS - Передача функции spyOn

HERE'S A LIVE DEMO

Я пытаюсь spyOn функцию из моего .service() из MainModel. В контроллере у меня есть отложенное обещание под названием natoAlphabet, которое успешно отображается на странице.

Сначала я ссылки getNato из MainController, но я никогда не ставил MainController.getNato в MainModel.getNato.

Поэтому я добавил в MainController:

this.getNato = MainModel.getNato; 

И я получаю ошибку: Expected spy getNato to have been called.

Однако в console log, если вы делаете вывод консольной mockMainCtrl контроллер осмеиваемым внутри beforeEach наверху вы получаете Object {name: "Hello World!", getNato: Promise}

, а затем ниже внутри первого теста it(), выход Object {name: "Hello World!"} однако, если вы расширяете, что один, вы получите:

Object {name: "Hello World!"} 
    getNato: Promise 
    name: "Hello world!"; 
    __proto__: Object 

В то время как один внутри beforeEach, вы имели getNato.

Моя ошибка

Моя ошибка происходит, когда проходит тест Жасмин и я получаю Expected spy getNato to have been called. от линии expect(mockMainCtrl.getNato).toHaveBeenCalled(); на theSpec.js.

Так что я делаю неправильно?

Не думаю, что что-то не так с app.js, потому что страница может успешно прочитать обещание.

Приложение:

theSpec.js:

describe('Controller: MainCtrl', function() { 

    beforeEach(module('app')); 

    var $scope, $q, mockMainCtrl, $controller, scope, deferred; 

    beforeEach(inject(function($controller, _$rootScope_, _$q_, MainModel) { 
    $q = _$q_; 
    $scope = _$rootScope_.$new(); 

    deferred = _$q_.defer(); 

    mockMainCtrl = $controller('MainCtrl', { 
     $scope: $scope, 
     MainModel: MainModel 
    }); 

    console.log(mockMainCtrl); 
    })); 

    it('spied and have been called', function() { 
    spyOn(mockMainCtrl, 'getNato'); 
    console.log(mockMainCtrl); 
    expect(mockMainCtrl.getNato).toHaveBeenCalled(); 
    }); 

    it('Name from service, instantiated from controller, to be mocked correctly', inject(function() { 
    expect(mockMainCtrl.name) 
     .toEqual("Hello World!"); 
    })); 

    it('Get [getNato] mocked deferred promise', function(mainCtrl) { 
    deferred.resolve([{ id: 1 }, { id: 2 }]); 
    $scope.$apply(); 
    expect($scope.results).not.toBe(undefined); 
    expect($scope.results).toEqual(['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot', 'Golf', 'Hotel', 'India']); 
    expect($scope.error).toBe(undefined); 
    }); 
}); 

app.js:

var app = angular.module('app', []); 

app.service('MainModel', function($q) { 
    this.name = "Hello World!"; 

    var getNato = function() { 
    var deferred = $q.defer(); 
    var theNatoAlphabet = ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot', 'Golf', 'Hotel', 'India']; 
    deferred.resolve(theNatoAlphabet); 
    return deferred.promise; 
    }; 

    this.getNato = getNato(); 
}); 

app.controller('MainCtrl', function($scope, MainModel) { 
    this.name = MainModel.name; 

    var self = this; 

    MainModel.getNato.then(function(data) { 
    self.natoAlphabet = data; 
    $scope.results = data; 
    }).catch(function() { 
    $scope.error = 'There has been an error!'; 
    }); 

    this.getNato = MainModel.getNato; 


}); 

ответ

1

Взгляните на - http://plnkr.co/edit/57ZA8BXscmdY6oDX5IOA?p=preview.

Вы хотите «spyOn» зависимости, то есть «MainModel», и сделать это перед конструкцией «$ controller», поскольку «обещание» становится решаемым при построении контроллера. Надеюсь это поможет.

Что-то вроде -

beforeEach(inject(function($controller, _$rootScope_, _MainModel_) { 
    scope = _$rootScope_.$new(); 
    MainModel = _MainModel_; 
    spyOn(MainModel, 'getNato').andCallThrough(); 
    mockMainCtrl = $controller('MainCtrl', { 
     $scope: scope 
    }); 
    })); 

    it('spied and have been called', function() { 
    expect(MainModel.getNato).toHaveBeenCalled(); 
    });