2017-10-08 71 views
0

在我的角JS应用程序中,我有一个mainController,它将userFactory作为参数。 userFactory由一个名为userService的对象组成,该对象又具有一个userDetails对象和一些包括resetUserDetails的方法。 (详见下页)使用Jasmine spyOn在工厂中定义的对象的方法

在mainController中我有一个logOut函数,它调用userFactory.userService.resetUserDetails方法。我想用茉莉花测试这个logOut函数,但是我收到了一些错误。我对茉莉花很陌生,所以很抱歉,如果它的东西明显我失踪了。

所以首先在我的Jasmine套件中创建一个MainControllerSpec来测试我的mainController。

在这个规范中,我注入了一个名为userFactory的工厂。我想我的spyOn方法resetUserDetails如下但得到一个错误:

spyOn(userFactory, 'userService.resetUserDetails'); 

错误:userService.resetUserDetails()不存在。

我想这个过程通过创建我的userFactory一个函数调用测试(userService对象之外)和它的作品以及至少我知道在规范的工厂注入设置了罚款。
任何帮助非常感谢。在mainController谢谢

MainControllerSpec.js

describe("MainController", function() { 
    beforeEach(angular.mock.module('mapModule', 'ngRoute','ngTouch', 'ngAnimate')); 
    var scope, userFactory; 

    beforeEach(inject(function($rootScope, $controller, _userFactory_){ 
     scope = $rootScope.$new(); 
     userFactory = _userFactory_; 
     $controller('mainController', { 
      $scope: scope 
     }); 
    })); 


    describe('The logOut function', function() { 
     it('should call the resetUserDetails function of the userFactory.userService object and reset the userDetails object', function() { 
      //spyOn takes in a factory and a method of that factory 
      spyOn(userFactory, 'userService.resetUserDetails'); 
      //spyOn(userFactory, 'test'); tried this and it works. 
      scope.logOut(); 
      expect(userFactory.userService.resetUserDetails).toHaveBeenCalled(); 
     }); 
    }); 

}); 

注销功能
$scope.logOut = function(){ 
     userFactory.userService.resetUserDetails(); 
     //userFactory.test(); //tried this with spyOn in jasmine 
    } 

userFactory

mapApp.factory('userFactory', function(){ 

    var userService = { 
     /* 
     * Initialize a userDetails object. 
     */ 
     userDetails : { 
      "userID" : null, 
      "facebookUserID" : "", 
      "facebookName" : "", 
      "facebookProfilePic" : "", 
      "userPrivilegeID" : 1, 
      "userToken" : "", 
      "isLoggedIn" : false 
     }, 
     resetUserDetails : function(){ 
      /* 
      * This method resets the userDetails object. 
      */ 
      this.userDetails = { 
       "userID" : null, 
       "facebookUserID" : "", 
       "facebookName" : "", 
       "facebookProfilePic" : "", 
       "userPrivilegeID" : 1, 
       "userToken" : "", 
       "isLoggedIn" : false 
      }; 
     } 
    }; 
    var test = function(){ 
     /* 
     * for testing spyOn in Jasmine 
     */ 
    }; 
    //return public API so that we can access it in all controllers 
    return{ 
     userService: userService, 
     test: test 
    }; 
}); 
+0

我刚copped它。道歉。以下工作正常。 spyOn(userFactory.userService,'resetUserDetails'); .. – Sarah

+0

通常你可能想要完全在控制器测试中模拟服务,而不是一个一个的监视它的方法。例如。 https://stackoverflow.com/a/46595428/3731501 – estus

+0

@estus好的谢谢你的建议。我会检查出 – Sarah

回答

1

你需要模拟你userFactory之前直接注入它。 单元测试的目标是将文件测试为黑盒子,而不直接测试相关方法的逻辑。

对于他们而言,您将编写userFactory的规格文件。

在这种情况下,你可以做的是类似如下:

describe("MainController", function() { 
 

 
    beforeEach(angular.mock.module('mapModule', 'ngRoute', 'ngTouch', 'ngAnimate')); 
 
    var scope, userFactory; 
 

 
    // here mock the methods of your factory 
 
    beforeEach(module(function($provide) { 
 
    $provide.value('userFactory', { 
 
     myFirstObject: { 
 
     myFirstMethod: function() {} 
 
     } 
 
    }); 
 
    })); 
 

 
    beforeEach(inject(function($rootScope, $controller, _userFactory_) { 
 
    scope = $rootScope.$new(); 
 
    userFactory = _userFactory_; 
 
    $controller('mainController', { 
 
     $scope: scope 
 
    }); 
 
    })); 
 

 

 
    describe('The logOut function', function() { 
 
    it('should call the resetUserDetails function of the userFactory.userService object and reset the userDetails object', function() { 
 
     //here spy on the method and return what you would like to return in this test 
 
     // or if you don't need to manage the return, as it seems you don't, just use callThrough 
 
     spyOn(userFactory.myFirstObject, 'myFirstMethod').and.callThrough(); 
 
     scope.logOut(); 
 
     expect(userFactory.myFirstObject.myFirstMethod).toHaveBeenCalled(); 
 
    }); 
 
    }); 
 

 
});

+0

谢谢。我明天会试一试。尽管我在上面的评论中看到了自己的代码,我需要这样说:spyOn(userFactory.userService,'resetUserDetails');而不是:spyOn(userFactory,'userService.resetUserDetails'); ..(因为我的方法是在userFactory内的一个名为userService的对象内)..但我感谢你的建议,并会尝试你的建议。谢谢 – Sarah

+0

哦对不起,没有注意到你的方法是在嵌套对象里面,更改了代码 – quirimmo

+0

谢谢你。我试过这个,很好,谢谢。但是我做了一件额外的事情(感谢评论中的另一个人)。我使用jasmine.createSpy()创建了一个间谍,因此$ provide.value('userFactory',{ myFirstObject:{ myFirstMethod:jasmine.createSpy() } });然后我并不需要在套件的测试中使用spyOn,而是继续使用其余的代码。无论如何,你的回答对我的问题是正确的,所以我现在就接受它。非常感谢你 – Sarah