2017-10-08 5 views
0

내 JS 애플리케이션에서 저는 userFactory를 매개 변수로 취하는 mainController를 가지고 있습니다. userFactory는 userService라는 객체로 구성되며, userDetails 객체와 resetUserDetails를 비롯한 일부 메소드가 있습니다. (아래 참조)Jasmine spyOn을 공장에서 정의 된 객체의 메소드와 함께 사용하기

mainController에는 userFactory.userService.resetUserDetails 메서드를 호출하는 logOut 함수가 있습니다. jasmine을 사용하여이 logOut 함수를 테스트하고 싶습니다. 그러나 오류가 발생합니다. 나는 Jasmine에게 아주 새롭다. 그래서 그 무엇인가 분명하지 않다면 사과한다.

먼저 Jasmine 제품군에서 mainController 테스트를 위해 MainControllerSpec을 만듭니다.

이 사양에서는 userFactory라는 팩토리를 주입하고 있습니다.

spyOn(userFactory, 'userService.resetUserDetails'); 

오류 : userService.resetUserDetails()이 존재하지 않는 그러나 나는 오류를 받고 다음과 같이 내 resetUserDetails 방법을 spyOn 것을 시도하고있다.

내 userFactory (userService 객체 외부)에 test라는 함수를 작성하여이 프로세스를 시도했지만 잘 작동하므로 spec의 factory injection이 잘 설정되었음을 알았습니다.
도움을 주시면 감사하겠습니다. 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

: 당신이 할 수있는 일이 경우

는 다음과 같은 것입니다. 사과. 다음은 잘 작동합니다. 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