유닛 테스트에서의 bindToController
bindToController를 사용하여 격리된 스코프를 컨트롤러에 직접 연결하도록 지시하고 있습니다.이 명령어는 다음과 같습니다.
app.directive('xx', function () {
return {
bindToController: true,
controller: 'xxCtrl',
scope: {
label: '@',
},
};
});
다음으로 HTML에서 라벨이 지정되지 않은 경우 컨트롤러에 기본값이 있습니다.
app.controller('xxCtrl', function () {
var ctrl = this;
ctrl.label = ctrl.label || 'default value';
});
재스민 유닛 테스트에서 xxCtrl을 인스턴스화해서 ctrl.label을 테스트하려면 어떻게 해야 하나요?
describe('buttons.RemoveButtonCtrl', function () {
var ctrl;
beforeEach(inject(function ($controller) {
// What do I do here to set ctrl.label BEFORE the controller runs?
ctrl = $controller('xxCtrl');
}));
it('should have a label', function () {
expect(ctrl.label).toBe('foo');
});
});
문제를 테스트하려면 선택하십시오.
각도 1.3(아래 1.4+ 참조)
앵귤러 파고들기JS 소스 코드 문서화되어 있지 않은 세 번째 인수를 찾았습니다.$controller
착신측 서비스later
($controller 소스 참조).
사실이라면$controller()
속성이 있는 함수를 반환합니다.instance
속성을 설정할 수 있습니다.
컨트롤러를 인스턴스화할 준비가 되면 함수를 호출하면 생성자에서 사용할 수 있는 속성을 사용하여 컨트롤러가 인스턴스화됩니다.
이 예에서는 다음과 같이 동작합니다.
describe('buttons.RemoveButtonCtrl', function () {
var ctrlFn, ctrl, $scope;
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
ctrlFn = $controller('xxCtrl', {
$scope: scope,
}, true);
}));
it('should have a label', function () {
ctrlFn.instance.label = 'foo'; // set the value
// create controller instance
ctrl = ctrlFn();
// test
expect(ctrl.label).toBe('foo');
});
});
업데이트된 Plunker(작동하려면 Angular를 업그레이드해야 합니다.지금은 1.3.0~rc.4입니다) : http://plnkr.co/edit/tnLIyzZHKqPO6Tekd804?p=preview
Angular 소스 코드를 인용하여 사용하는 것은 권장되지 않습니다.
나중에 컨트롤러 인스턴스화:이 기계는 컨트롤러의 생성자 자체를 호출하기 전에 개체의 인스턴스를 만드는 데 사용됩니다.
이를 통해 컨스트럭터를 호출하기 전에 컨트롤러에 속성을 추가할 수 있습니다.주로 스코프 바인딩을 $compile로 분리하기 위해 사용됩니다.
이 기능은 응용 프로그램에서 사용하도록 설계되지 않았기 때문에 공개적으로 문서화되어 있지 않습니다.
단, 컨트롤러를 테스트하는 메커니즘이 없습니다.bindToController: true
그래도 쓰게 해줬는데..앵귤러 놈들이 깃발을 공개하는 걸 고려해봐야 할 것 같아
보닛 아래에는 임시 건설사를 사용하고 있고, 우리가 직접 쓸 수도 있을 것 같습니다.
솔루션의 장점은 생성자가 두 번 호출되지 않는다는 것입니다. 이 경우 속성에 예시와 같이 기본값이 없으면 문제가 발생할 수 있습니다.
각도 1.4 이상(2015-12-06 업데이트):
Angular 팀은 버전 1.4.0에서 이를 직접 지원했습니다(#9425 참조).
오브젝트를 전달하기만 하면 됩니다.$controller
기능:
describe('buttons.RemoveButtonCtrl', function () {
var ctrl, $scope;
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('xxCtrl', {
$scope: scope,
}, {
label: 'foo'
});
}));
it('should have a label', function () {
expect(ctrl.label).toBe('foo');
});
});
이 블로그 투고도 참조해 주세요.
ES6를 사용한 BindToController 유닛 테스트
ES6를 사용하는 경우 컨트롤러를 직접 Import하여 앵글모크를 사용하지 않고 테스트할 수 있습니다.
지시:
import xxCtrl from './xxCtrl';
class xxDirective {
constructor() {
this.bindToController = true;
this.controller = xxCtrl;
this.scope = {
label: '@'
}
}
}
app.directive('xx', new xxDirective());
컨트롤러:
class xxCtrl {
constructor() {
this.label = this.label || 'default value';
}
}
export default xxCtrl;
컨트롤러 테스트:
import xxCtrl from '../xxCtrl';
describe('buttons.RemoveButtonCtrl', function () {
let ctrl;
beforeEach(() => {
xxCtrl.prototype.label = 'foo';
ctrl = new xxCtrl(stubScope);
});
it('should have a label', () => {
expect(ctrl.label).toBe('foo');
});
});
자세한 내용은 다음을 참조하십시오. ES6 모듈을 사용한 Angular JS 애플리케이션의 적절한 장치 테스트
제 의견으로는 이 컨트롤러는 단독으로 테스트하는 것이 아닙니다.이 컨트롤러는 단독으로 테스트하는 것은 아닙니다.
app.controller('xxCtrl', function () {
var ctrl = this;
// where on earth ctrl.lable comes from???
ctrl.newLabel = ctrl.label || 'default value';
});
스코프 속성 수신에 의존하는 명령어와 밀접하게 결합되어 있습니다.재사용할 수 없습니다.이 컨트롤러를 보면 이 변수가 어디서 나오는 건지 궁금해요.이는 외부 스코프의 변수를 사용하여 내부적으로 누출 기능을 수행하는 것과 다를 바 없습니다.
function Leaky () {
... many lines of code here ...
// if we are here we are too tired to notice the leakyVariable:
importantData = process(leakyVariable);
... mode code here ...
return unpredictableResult;
}
이제 누출 기능이 있습니다. 이 함수의 동작은 변수에 따라 매우 예측할 수 없습니다.leakyVariable
함수가 호출되는 범위에 관계없이 표시(또는 표시되지 않음)합니다.
당연히 이 기능은 테스트하기에는 악몽입니다.이것은 실제로 좋은 것입니다.아마 개발자가 기능을 모듈러형으로 다시 쓰게 하고 재사용할 수 있게 하는 것입니다.어려운 것은 아닙니다.
function Modular (outsideVariable) {
... many lines of code here ...
// no need to hit our heads against the wall to wonder where the variable comes from:
importantData = process(outsideVariable);
... mode code here ...
return predictableResult;
}
누출 문제가 없고 테스트와 재사용이 매우 용이합니다.가 의 좋은 것을 하는 것은$scope
더 나은 방법입니다.
app.controller('xxCtrl', function ($scope) {
$scope.newLabel = $scope.label || 'default value';
});
심플하고, 짧고, 테스트도 간단합니다.또한 부피가 큰 지시 객체 정의도 없습니다.
이면에 있는 최초의 이유는controllerAs
구문은 부모로부터 상속받은 누출 범위입니다.그러나 디렉티브의 고립된 범위는 이미 이 문제를 해결했습니다.따라서 벌크 리크 구문을 사용할 이유가 없습니다.
저는 특별히 우아하지는 않지만 적어도 효과가 있는 방법을 찾았습니다(더 좋은 옵션이 있다면 코멘트를 남겨주세요.
이 명령에서 "가져온" 값을 설정하고 컨트롤러 함수를 다시 호출하여 그 기능을 테스트합니다.도우미 "invoke Controller"를 더 드라이하게 만들었습니다.
예를 들어 다음과 같습니다.
describe('buttons.RemoveButtonCtrl', function () {
var ctrl, $scope;
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('xxCtrl', {
$scope: scope,
});
}));
it('should have a label', function () {
ctrl.label = 'foo'; // set the value
// call the controller again with all the injected dependencies
invokeController(ctrl, {
$scope: scope,
});
// test whatever you want
expect(ctrl.label).toBe('foo');
});
});
beforeEach(inject(function ($injector) {
window.invokeController = function (ctrl, locals) {
locals = locals || {};
$injector.invoke(ctrl.constructor, ctrl, locals);
};
}));
언급URL : https://stackoverflow.com/questions/25837774/bindtocontroller-in-unit-tests
'programing' 카테고리의 다른 글
각도 뒤에 jQuery 코드 실행JS가 HTML 렌더링을 완료합니다. (0) | 2023.03.17 |
---|---|
Angular에서의 서비스 콜 상대 경로 사용JS (0) | 2023.03.17 |
jquery의 ajax 함수에서 비동기 false 및 비동기 true를 사용하는 경우 (0) | 2023.03.17 |
잘못된 구성 개체입니다.API 스키마와 일치하지 않는 구성 개체를 사용하여 웹 팩이 초기화되었습니다. (0) | 2023.03.17 |
리액트 라우터를 통해 설정된 경로에서 Redx Store에 액세스하는 방법 (0) | 2023.03.17 |