컨트롤러를 글로벌하게 하지 않고 Angular에서 유닛 테스트 지시 컨트롤러
Vojta Jina의 뛰어난 저장소에서 디렉티브 컨트롤러를 모듈 래퍼 외부에 정의합니다.여기를 참조해 주세요.https://github.com/vojtajina/ng-directive-testing/blob/master/js/tabs.js
그것은 나쁜 관행이고 세계적인 네임스페이스를 오염시키지 않나요?
어떤 것을 Tabs Controller라고 부르는 것이 논리적인 다른 장소를 갖게 되면, 그 장소가 망가지는 것은 아닐까요?
전술한 디렉티브에 대한 테스트는 https://github.com/vojtajina/ng-directive-testing/commit/test-controller 에서 확인할 수 있습니다.
글로벌 네임스페이스에 컨트롤러를 배치하지 않고 디렉티브컨트롤러를 다른 디렉티브컨트롤러와 분리하여 테스트할 수 있습니까?
전체 디렉티브를 app.directive(...) 정의로 캡슐화하는 것이 좋습니다.
나는 가끔 명령어와 함께 내 컨트롤러를 포함하는 것을 선호하기 때문에 그것을 테스트할 방법이 필요하다.
우선 지시사항
angular.module('myApp', [])
.directive('myDirective', function() {
return {
restrict: 'EA',
scope: {},
controller: function ($scope) {
$scope.isInitialized = true
},
template: '<div>{{isInitialized}}</div>'
}
})
그런 다음 테스트:
describe("myDirective", function() {
var el, scope, controller;
beforeEach inject(function($compile, $rootScope) {
# Instantiate directive.
# gotacha: Controller and link functions will execute.
el = angular.element("<my-directive></my-directive>")
$compile(el)($rootScope.$new())
$rootScope.$digest()
# Grab controller instance
controller = el.controller("myDirective")
# Grab scope. Depends on type of scope.
# See angular.element documentation.
scope = el.isolateScope() || el.scope()
})
it("should do something to the scope", function() {
expect(scope.isInitialized).toBeDefined()
})
})
인스턴스화된 지시문에서 데이터를 가져오는 자세한 방법은 angular.element 설명서를 참조하십시오.
디렉티브 인스턴스화는 컨트롤러 및 모든 링크 기능이 이미 실행되었음을 의미하므로 테스트에 영향을 줄 수 있습니다.
훌륭한 질문입니다!
따라서 이는 컨트롤러뿐만 아니라 지시가 그 작업을 수행하기 위해 필요할 수 있는 서비스에서도 공통적으로 우려되는 사항이지만, 반드시 이 컨트롤러/서비스를 "외부"에 공개하고 싶지는 않습니다.
글로벌 데이터는 악성이며 피해야 하며 이는 디렉티브 컨트롤러에도 적용됩니다.이 전제를 도입하면, 이러한 컨트롤러를 「로컬」로 정의하기 위해서, 몇개의 다른 어프로치를 취할 수 있습니다.그 동안 컨트롤러는 유닛 테스트에 "간단하게" 접근할 수 있어야 하므로 단순히 명령어 폐쇄에 숨길 수 없습니다.IMO의 가능성은 다음과 같습니다.
1) 우선 모듈레벨에서 디렉티브의 컨트롤러를 간단하게 정의할 수 있습니다.예를 들어 다음과 같습니다.
angular.module('ui.bootstrap.tabs', [])
.controller('TabsController', ['$scope', '$element', function($scope, $element) {
...
}])
.directive('tabs', function() {
return {
restrict: 'EA',
transclude: true,
scope: {},
controller: 'TabsController',
templateUrl: 'template/tabs/tabs.html',
replace: true
};
})
이것은 Vojta의 작업을 기반으로 한 https://github.com/angular-ui/bootstrap/blob/master/src/tabs/tabs.js에서 사용하고 있는 간단한 기술입니다.
이것은 매우 간단한 기술이지만 컨트롤러는 여전히 애플리케이션 전체에 노출되어 있기 때문에 다른 모듈이 이를 덮어쓸 수 있습니다.이러한 의미에서 컨트롤러를 Angular에 로컬로 만듭니다.JS 응용 프로그램(글로벌 창 범위를 오염시키지 않음)뿐만 아니라 모든 Angular에 글로벌하게 적용됩니다.JS 모듈
2) Closure Scope와 특수 파일 셋업을 사용하여 테스트한다.
컨트롤러 기능을 완전히 숨기려면 코드를 폐쇄형으로 감쌀 수 있습니다.이 기술은 Angular가JS가 사용하고 있다.예를 들어 NgModelController를 보면 자체 파일에서 "글로벌" 함수로 정의되어 있으며(따라서 테스트를 위해 쉽게 액세스할 수 있음), 빌드 시간 동안 파일 전체가 닫힙니다.
- https://github.com/angular/angular.js/blob/master/src/angular.prefix
- https://github.com/angular/angular.js/blob/master/src/angular.suffix
정리하면, 옵션 (2)는 「안전」하지만, 빌드에는 사전에 설정이 필요합니다.
제임스의 방법은 나에게 효과가 있다.단, 외부 템플릿이 있는 경우 $httpBackend를 호출해야 합니다.$rootScope 앞에 flush()를 입력합니다.각도가 컨트롤러를 실행할 수 있도록 하기 위해 $squal()을 지정합니다.
https://github.com/karma-runner/karma-ng-html2js-preprocessor 를 사용하고 있는 경우는, 이것은 문제가 되지 않는다고 생각합니다.
이런 식으로 하는 게 뭐가 잘못됐나요?컨트롤러를 글로벌 네임스페이스에 배치하지 않고 불필요한 $compiling html 없이 원하는 것(컨트롤러 등)을 테스트할 수 있으므로 권장됩니다.
지시 정의 예:
.directive('tabs', function() {
return {
restrict: 'EA',
transclude: true,
scope: {},
controller: function($scope, $attrs) {
this.someExposedMethod = function() {};
},
templateUrl: 'template/tabs/tabs.html',
replace: true
};
그런 다음 Jasmine 테스트에서 "name + Directive"(예: "tabs Directive")를 사용하여 작성한 디렉티브를 묻습니다.
var tabsDirective = $injector.get('tabsDirective')[0];
// instantiate and override locals with mocked test data
var tabsDirectiveController = $injector.instantiate(tabsDirective.controller, {
$scope: {...}
$attrs: {...}
});
이제 컨트롤러 방식을 테스트할 수 있습니다.
expect(typeof tabsDirectiveController.someExposedMethod).toBe('function');
IIFE를 사용하면 글로벌 네임스페이스 경합을 회피할 수 있습니다.또, 복잡한 인라인 체조를 회피할 수 있어 스코프의 자유도 얻을 수 있습니다.
(function(){
angular.module('app').directive('myDirective', function(){
return {
.............
controller : MyDirectiveController,
.............
}
});
MyDirectiveController.$inject = ['$scope'];
function MyDirectiveController ($scope) {
}
})();
언급URL : https://stackoverflow.com/questions/15314293/unit-testing-directive-controllers-in-angular-without-making-controller-global
'source' 카테고리의 다른 글
*ngFor에 필터를 적용하는 방법 (0) | 2023.03.18 |
---|---|
Woocommerce에서 주문을 위한 메타 추가 (0) | 2023.03.18 |
GraphQL에서 "edge"와 "node"의 의미는 무엇입니까? (0) | 2023.03.18 |
관찰 가능한 서브스크립션이 포함된 함수의 값을 반환하려면 어떻게 해야 합니까? (0) | 2023.03.18 |
Angular js에서 모듈 오류를 인스턴스화하지 못했습니다. (0) | 2023.03.18 |