2016-06-03 2 views
2

처음으로 jasmine을 배우고 각도 서비스에서 focus() 기능을 테스트하려고 할 때이 오류가 발생합니다. 여기 는 서비스 : 여기 angularjs + jasmine : 서비스에서 포커스 테스트

myApp.service('MyService', function($timeout, $window) { 
    var service = { 
    focusElem: focusElem 
    }; 
    return service; 

    function focusElem(id) { 
    console.log('id of element is = ', id); 
    if (id) { 

     $timeout(function() { 
     var element = $window.document.getElementById(id); 
     console.log('element is = ', element); 
     if (element) { 
      element.focus(); 
     } 
     }); 
    } 
    }; 

}); 

내 사양 파일입니다

describe('myApp', function() { 
    var element, dummyElement; 
    beforeEach(function() { 
    // Initialize myApp injector 
    module('myApp'); 

    // Inject instance of service under test  
    inject(function($injector) { 
     MyServiceObj = $injector.get('MyService'); 
    }); 

    element = angular.element('<input id="firstName" name="firstName"/>'); 
    dummyElement = document.createElement('input'); 
    dummyElement.setAttribute('id', 'lastName'); 

    }); 

    it('should have focus if the focus Service is used on an element', function() { 
    console.info('------------------'); 
    spyOn(element[0], 'focus'); 
    spyOn(dummyElement, 'focus'); 
    MyServiceObj.focusElem(dummyElement.getAttribute('id')); 
    expect(dummyElement.focus).toHaveBeenCalled(); 
    }); 
}); 

내 오류 : 당신 ngMock 많은 서비스를 사용하고 이렇게 변경하면

myApp should have focus if the focus Service is used on an element 
Expected spy focus to have been called. 
Error: Expected spy focus to have been called. 
+0

[카르마와 앵글로 쟈스민 모의 체인으로 연결된 방법] ([http://stackoverflow.com/questions/36285896/jasmine-mock-chained-methods-with-karma-and-angular)의 가능한 복제본 – estus

+0

http : 'focus'가'callThrough'이고 포커스 이벤트를 트리거하는 경우 //stackoverflow.com/a/33742298/3731501 – estus

+0

이 기능을 사용하셨습니까? – tasseKATT

답변

1

가 제어 할 수 테스트 코드 내에서 동기식 방식으로 흐름을보다 잘 제어 할 수 있습니다.

영향을받는 서비스 중 하나는 $timeout입니다.

귀하의 서비스 내부에서 $timeout으로 전달 된 기능은 사용자가 말하지 않는 한 테스트에서 실행되지 않습니다.

은 다음과 같이 사용 $timeout.flush()을 실행하도록 지시하려면, 당신은 $timeout 서비스에 대한 참조가 필요

spyOn(element[0], 'focus'); 

spyOn(dummyElement, 'focus'); 

MyServiceObj.focusElem(dummyElement.getAttribute('id')); 

$timeout.flush(); 

expect(dummyElement.focus).toHaveBeenCalled(); 

참고 :

var element, dummyElement, $timeout; 

beforeEach(function() { 

    module('myApp'); 

    inject(function($injector, _$timeout_) { 

    MyServiceObj = $injector.get('MyService'); 

    $timeout = _$timeout_; 
    }); 

을 다음 문제에 다음 줄에 기인하여 서비스 :

var element = $window.document.getElementById(id); 

테스트에서 만드는 요소 DOM에 연결되지 않으므로 서비스에서 찾지 않습니다.

가장 쉬운 방법은 요소를 DOM에 첨부하는 것입니다. 이 경우 Jasmine은 전체 테스트 스위트에서 동일한 DOM을 사용하기 때문에 테스트 후에 수동으로 제거하는 것이 중요합니다. 예를 들어

:

it('should have focus if the focus Service is used on an element', function() { 

    var body = angular.element(document.body); 

    body.append(element); 
    body.append(dummyElement); 

    spyOn(element[0], 'focus'); 

    spyOn(dummyElement, 'focus'); 

    MyServiceObj.focusElem(dummyElement.getAttribute('id')); 

    $timeout.flush(); 

    expect(dummyElement.focus).toHaveBeenCalled(); 

    element.remove(); 
    dummyElement.remove(); 
}); 

데모 :http://plnkr.co/edit/F8xqfYYQGa15rwuPPbN2?p=preview

지금, 부착 및 단위 테스트 중에 DOM에 요소를 제거하는 것이 항상 좋은 것은 아니며, 지저분한 얻을 수 있습니다.

getElementById을 감시하고 반환 값을 제어하거나 전체 문서를 조롱하는 등 다른 방법으로 처리 할 수 ​​있습니다. 나는 여기에 그것의 예가 이미 있음을 확신하지만 여기에 들어가지 않을 것입니다.

관련 문제