2014-04-13 15 views
4

類似問題:Jasmine angularjs - spying on a method that is called when controller is initialized茉莉angularjs - 上稱爲角本地存儲方法刺探當控制器被初始化

以我控制器I使用所述角度本地存儲包通過注射,以提供localStorageService。

在我的單元測試中我想確保數據是從服務中檢索的,所以我窺探了「get」和「add」方法並嘲笑它們(.andCallFake)。

對於通過$ scope調用的所有方法,這可以正常工作$ watch - 只要我強制$摘要。但是對於在控制器初始化時調用的方法,它似乎不起作用。 任何人都可以建議爲什麼這不起作用?

應用> Main.js

​​3210

測試> Main.js

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

    // load the controller's module 
    beforeEach(module('angularTodoApp')); 

    var MainCtrl, 
    scope, 
    localStorageService, 
    store = []; 

    // Initialize the controller and a mock scope 
    beforeEach(inject(function ($controller, $rootScope, _localStorageService_) { 
    scope = $rootScope.$new(); 
    localStorageService = _localStorageService_; 
    MainCtrl = $controller('MainCtrl', { 
     $scope: scope, 
     localStorageService: _localStorageService_ 
    }); 

    //mock localStorageService get/add 
    spyOn(localStorageService,'get').andCallFake(function(key){ 
     return store[key]; 
    }); 
    spyOn(localStorageService,'add').andCallFake(function(key, val){ 
     store[key] = val; 
    }); 
    })); 

    it('should retrieve "todos" from the store and assign to scope', function() { 
    expect(localStorageService.get).toHaveBeenCalledWith('todos'); 
    expect(scope.todos.length).toBe(0); 
    }); 

    it('should add items to the list and update the store for key = "todos"', function() { 
    scope.todo = 'Test 1'; 
    scope.addTodo(); 
    scope.$digest(); 
    expect(localStorageService.add).toHaveBeenCalledWith('todos', jasmine.any(String)); 
    expect(scope.todos.length).toBe(1); 
    }); 

所有測試都通過,除了一個在構造:

expect(localStorageService.get).toHaveBeenCalledWith('todos'); 

回答

5

其原因是控制器在您撥打$controller的位置進行初始化,在您的示例中爲之前您通過spyOn創建了間諜。您的示例的解決方案是將電話$controller移動到調用spyOn

對於更長的測試套件,爲了保持乾燥,您可能必須將呼叫$controller置於單獨的功能中,以便在您嘲笑任何所需的服務後再打電話。

+1

是的,當我醒來時,我才意識到。上帝永遠不要熬夜,並試圖弄清楚它!謝謝!接受,upvoted。 –

3

更新測試套件,確保嘲笑到位之前呼叫控制器構造:

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

    // load the controller's module 
    beforeEach(module('angularTodoApp')); 

    var MainCtrl, 
    scope, 
    localStorageService, 
    store; 

    // Initialize the controller and mocks 
    beforeEach(inject(function ($controller, $rootScope, _localStorageService_) { 
    store = []; //clear the store before each test 
    scope = $rootScope.$new(); 
    localStorageService = _localStorageService_; 

    //mock localStorageService get/add 
    spyOn(localStorageService,'get').andCallFake(function(key){ 
     return store[key]; 
    }); 
    spyOn(localStorageService,'add').andCallFake(function(key, val){ 
     store[key] = val; 
    }); 

    //Instantiate controller to test 
    MainCtrl = $controller('MainCtrl', { 
     $scope: scope, 
     localStorageService: localStorageService 
    }); 
    })); 

    it('should retrieve "todos" from the store and assign to scope', function() { 
    expect(localStorageService.get).toHaveBeenCalledWith('todos'); 
    expect(scope.todos.length).toBe(0); 
    }); 

    it('should add items to the list and update the store for key = "todos"', function() { 
    scope.todo = 'Test 1'; 
    scope.addTodo(); 
    scope.$digest(); 
    expect(localStorageService.add).toHaveBeenCalledWith('todos', jasmine.any(String)); 
    expect(scope.todos.length).toBe(1); 
    }); 

    it('should remove items to the list and update the store', function() { 
    scope.todo = 'Test 1'; 
    scope.addTodo(); 
    scope.$digest(); 
    //reset call count 
    localStorageService.add.reset(); 

    scope.removeTodo(0); 
    scope.$digest(); 
    expect(localStorageService.add).toHaveBeenCalledWith('todos', jasmine.any(String)); 
    expect(scope.todos.length).toBe(0); 
    }); 
}); 
+0

我做了像你的代碼確切的變化,現在出現錯誤 '控制器:MainCtrl應該添加項目列表並更新商店的關鍵=「todos」失敗 [本機代碼] })>]但它是從未打過電話 錯誤:預期的間諜添加被稱爲['todos',

+0

您能否將您的代碼放在主要位置?我一直在忙於Docker和基礎架構,並將Angular代碼交給了一位同事,因此除了概覽視角外,我還沒有一直工作了近一年.... - 但我可以嘗試幫助。 –

+1

好吧,你的幫助提供,我已經找到了答案,我找到了一個地方,我應該增加超時,因爲它似乎是有一段時間之前,服務模擬是emuated。現在它運作良好 –

1

您還需要在您的beforeEach(在LocalStorageModule)呼籲在test.js文件加載模塊。

beforeEach(module('angularTodoApp', 'LocalStorageModule')); 

另外,不要忘記更新您的karma.conf.js文件

module.exports = function(config) { 
    // ... 
    files: [ 
     '/path/to/angular.min.js', 
     '/path/to/angular-mocks.js', 
     '/path/to/angular-local-storage.js', 
     'Main/test.js', 
     'Main/app.js' 
    ], 
    //... 

我只是無意中發現了同樣的問題,這並獲得成功對我來說。

最後,您還需要修改spyOn(...).andCallFake(...)通話,如果你正在使用茉莉花2.4 spyOn(...).and.callFake(...)

在以前的答案給出的方法不茉莉花2.4工作(在以前的版本沒有測試過,雖然)。