角度单元测试,SpyOn独立函数

时间:2017-01-06 20:44:49

标签: javascript angularjs unit-testing jasmine

我正在使用Jasmine测试一个Angular应用程序,并希望在调用控制器的ready()函数时测试我的控制器中的getItem()函数。

---控制器---

var vm = this;
vm.items = [];
$ionicPlatform.ready(ready);

function ready() {
     vm.items.push(getItem());

     function getItem(){
          var item = //do stuff to get item;
          console.log('getItem called');
          return item;
     }
}

--- Spec ---

describe('Controller', function(){

     //--- Load app with dependencies and module to test code omitted.

     beforeEach(function(){
          //How do I spy on getItem() to test that it was called?
          //I've tried getItem = jasmine.createSpy()
          //I've tried spyOn(window, 'getItem')
     }

     //--- Initialize the controller and a mock scope code omitted.

     beforeEach(function(done){
          $ionicPlatform.ready(function(){
               done();
          });
     });

     it('getItem function should get called', function(){
          expect(getItem).toHaveBeenCalled();

          //--- Note, getItem does not get called according to the expect statement, 
          //--- but does output 'getItem called' to the terminal when running the test.
     });

});

1 个答案:

答案 0 :(得分:0)

不幸的是,您已经使用Jasmine实现了Javascript单元测试的基本限制 - 您只能在某些对象上公开spyOn个方法。如果某个函数是另一个函数的内部函数,并且无论如何都没有公开,则无法直接测试它。

但是,您有两种选择:

  1. 以可以监视的方式公开该函数(通常作为您正在测试的任何Angular组件的方法)。
  2. 间接测试。
  3. 第一个可能是相对不言而喻的,但后者可能有点混乱。基本上,如果调用getItems函数,则无法直接测试 ,但该函数可能具有它调用的下游方法,或者可以测试它的更改值。例如,您可以在调用vm.items.push后测试ready更大,或者spyOn(console.log)expect(console.log).toHaveBeenCalledWith('getItem called')

    你可以在互联网上找到两种方法的论据 - 我倾向于选择方法二,因为我不喜欢为了可测试性而单独使用重构,但很多人会争辩说重构可测试性通常会产生更好的代码。那是你的选择。希望这有帮助!