简体   繁体   English

角度单元测试,SpyOn独立功能

[英]Angular Unit Test, SpyOn stand-alone function

I am using Jasmine to test an Angular app and would like to test that the getItem() function within my controller is called when the ready() function of the controller is called. 我正在使用Jasmine测试Angular应用程序,并想测试在调用控制器的ready()函数时调用了控制器内的getItem()函数。

--- Controller --- -控制器-

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.
     });

});

Unfortunately, you've come upon a fundamental limit of Javascript unit testing with Jasmine-- you can only spyOn methods that are exposed on some object. 不幸的是,您遇到了使用Jasmine进行Javascript单元测试的基本限制-您只能对某些对象公开的spyOn方法。 If there is a function that is internal to another function, and not exposed in anyway, you cannot test it directly. 如果某个功能是另一个功能的内部功能,并且无论如何都没有公开,则无法直接对其进行测试。

However, you do have two options available to you: 但是,您确实有两个可用选项:

  1. Expose the function in a way that it can be spied on (generally as a method of whatever Angular component you are testing). 以可以窥探的方式公开该功能(通常作为要测试的任何Angular组件的一种方法)。
  2. Test it indirectly. 间接测试。

The first is probably relatively self-evident, but the latter may be a little confusing. 前者可能是不言而喻的,但后者可能会有些混乱。 Basically, you can't test directly if the getItems function is called, but the function may have downstream methods it calls or values it changes you can test. 基本上,您不能直接测试是否调用了getItems函数,但是该函数可能具有其调用的下游方法或您可以测试的更改值。 For instance, you can test that vm.items.push is larger after ready is called, or you can spyOn(console.log) and expect(console.log).toHaveBeenCalledWith('getItem called') . 例如,可以在调用ready之后测试vm.items.push是否更大,或者可以spyOn(console.log)expect(console.log).toHaveBeenCalledWith('getItem called')

You can find arguments for both approaches on the internet-- I tend to prefer approach two because I don't like doing refactors solely for the purpose of testability, but many will argue that refactoring for testability generally yields better code. 您可以在Internet上找到两种方法的论点-我倾向于使用第二种方法,因为我不喜欢出于可测试性的目的进行重构,但是许多人会认为针对可测试性的重构通常会产生更好的代码。 That choice is yours to make. 该选择权由您决定。 Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM