2015-08-26 128 views
0

我想測試一個角度控制器嘲笑使用茉莉花工廠的調用。我的控制器是這樣的:如何測試茉莉花嘲笑服務的控制器

(function() { 
    'use strict'; 

    function initScoresController(scoresFactory){ 
    var vm = this; 
    vm.projects = {}; 
    vm.month = {}; 
    vm.month.users = {}; 
    vm.tally = {}; 
    vm.tally.projects = {}; 

    scoresFactory.projectsCurrentMonthScores().success(
     function(data){ 
     vm.projects = data; 
     } 
    ); 

    scoresFactory.usersCurrentMonthScores().success(
     function(data){ 
     vm.month.users = data; 
     } 
    ); 

    scoresFactory.projectCurrentMonthTally().success(
     function(data){ 
     vm.tally.projects = data; 
     } 
    ); 
    } 

    angular.module('project.dashboard') 
    .controller('ScoresController', ['scoresFactory', initScoresController]) 
})(); 

我廠是這樣的:

(function() { 
    'use strict'; 

    function setupScoresFactory($http, PROJECTS_CURRENT_MONTH_SCORES, USERS_CURRENT_MONTH_SCORES, PROJECT_CURRENT_MONTH_TALLY){ 

    var scoresFactory = {}; 

    scoresFactory.projectsCurrentMonthScores = function(){ 
     return $http.get(PROJECTS_CURRENT_MONTH_SCORES); 
    }; 

    scoresFactory.usersCurrentMonthScores = function(){ 
     return $http.get(USERS_CURRENT_MONTH_SCORES); 
    }; 

    scoresFactory.projectCurrentMonthTally = function(){ 
     return $http.get(PROJECT_CURRENT_MONTH_TALLY); 
    }; 

    return scoresFactory; 

    }; 

    angular 
    .module('project.dashboard', ["config"]) 
    .factory('scoresFactory', ['$http', 'PROJECTS_CURRENT_MONTH_SCORES', 'USERS_CURRENT_MONTH_SCORES', 'PROJECT_CURRENT_MONTH_TALLY', setupScoresFactory]); 
})(); 

而且我的測試:

describe('dashboard scores controller', function(){ 
describe('projectCurrentMonthTally function', function(){ 
    var controller, scoresCtrl, scoresFactoryMock; 

    beforeEach(module('config')); 
    beforeEach(module('project.dashboard')); 

    beforeEach(
    inject(function(_$controller_, _scoresFactory_){ 
     controller = _$controller_; 
     scoresFactoryMock = _scoresFactory_; 

     jasmine.spyOn(scoresFactoryMock, 'projectsCurrentMonthScores').andReturn(function(){console.log('fake project current month')}); 

     scoresCtrl = controller('ScoresController', {scoresFactory: scoresFactoryMock}); 
    })); 

    it('it should return a collection of votes for every project', function(){ 
     expect(scoresFactoryMock.projectsCurrentMonthScores).toHaveBeenCalled(); 
    }); 
}); 
}); 

我的測試拋出這個錯誤:

TypeError: undefined is not a function 
    at Object.<anonymous> (http://localhost:8081/base/test/spec/dashboard/dashboard.scores.controller.js:13:16) 
    at Object.invoke (http://localhost:8081/base/bower_components/angular/angular.js:4473:17) 
    at Object.workFn (http://localhost:8081/base/bower_components/angular-mocks/angular-mocks.js:2401:20) 

我相信問題出在我的成功()調用上。我如何測試這個控制器,嘲笑我的工廠的電話?

回答

0

問題是你的工廠方法應該返回一個承諾,但你在模擬中返回一個函數。至少你需要返回一個有success()方法的東西。

一個簡單的辦法,使錯誤消失將是:

jasmine.spyOn(scoresFactoryMock,'projectsCurrentMonthScores').andReturn({ 
    success: function() { console.log('fake project current month') } 
}); 

但是:

我建議不要,因爲它包含了特殊的恢復在你們工廠$http獲得擴展的承諾success()並非所有承諾都有的方法(承諾通常只有一個then()方法)。我建議你改變你的工廠那樣:

scoresFactory.projectsCurrentMonthScores = function(){ 
    return $http.get(PROJECTS_CURRENT_MONTH_SCORES).then(function(response) { 
     return response.data; 
    }); 
}; 

當然,你必須改變你的控制器像那樣:

scoresFactory.projectsCurrentMonthScores().then(function(data){ 
    vm.projects = data; 
}); 

不過這樣一來你的控制器不關心是否是從獲得的數據$ http調用或其他方式(實際上你的控制器不應該在意!)。

在你的模擬你可以使用$ Q服務這樣創建一個承諾:

jasmine.spyOn(scoresFactoryMock, 'projectsCurrentMonthScores').andCallFake(function(){ 
    var deferred = $q.defer(); 
    return deferred.promise; 
}); 
+0

我給你建議的修正,但仍然有同樣的錯誤。 –

+0

兩件事:1)在你的代碼中,它說jasmine.spyOn(...)。我認爲它應該只是spyOn(...)。至少它不適用於茉莉花1.3。 2)我建議你根據我的建議更改工廠中的所有方法,並且全部監視它們,因爲它們將在測試中被調用。 – lex82

+0

我做了一個代碼的小提琴,你可以看到它的工作原理(我註釋了其他方法沒有被察覺)。 http://jsfiddle.net/L8kbzced/2/當前代碼顯示您正在觀察的問題。在第85行左右,您可以看到我在評論中提出的更改。只取消它的註釋並刪除舊的部分,你會看到它的作品。 – lex82

相關問題