Javascript 在我的指令中,如何测试正在调用的范围函数?
在我的指令中,如何测试正在调用的范围函数 我在Angular版本1中使用jasmine、karma runner和js单元测试 这是我的指令代码:Javascript 在我的指令中,如何测试正在调用的范围函数?,javascript,angularjs,unit-testing,testing,jasmine,Javascript,Angularjs,Unit Testing,Testing,Jasmine,在我的指令中,如何测试正在调用的范围函数 我在Angular版本1中使用jasmine、karma runner和js单元测试 这是我的指令代码: angular.module("myApp.directives") .directive("test", ["$rootScope", function($rootScope) { return { restrict: "E", scope: {
angular.module("myApp.directives")
.directive("test", ["$rootScope", function($rootScope) {
return {
restrict: "E",
scope: {
"figures": "="
},
templateUrl: "templates/components/test.html",
link: function(scope) {
scope.init = function() {
if (scope.figures !== undefined) {
for (let i = 0; i < scope.figures.length; i++) {
scope.figures[i].isModalVisible = false;
}
}
};
scope.init ();
}
};
}]);
describe("test", function () {
var element,
scope,
otherScope
mockData = [
{
isModalVisible: true
},
{
isModalVisible: false
}
];
beforeEach(angular.mock.module("myApp.directives"));
beforeEach(inject(function($rootScope, $compile) {
scope = $rootScope.$new();
scope.agg = mockData;
element = "<test figures=\"agg\"></test>";
element = $compile(element)(scope);
angular.element(document.body).append(element);
scope.$digest();
otherScope = element.isolateScope();
spyOn(otherScope, "init");
}));
//This one doesn't work
it("should close all modals by default", function () {
expect(otherScope.init).toHaveBeenCalled();
});
});
angular.module(“myApp.directives”)
.directive(“test”[“$rootScope”),function($rootScope){
返回{
限制:“E”,
范围:{
“数字”:“=”
},
templateUrl:“templates/components/test.html”,
链接:功能(范围){
scope.init=函数(){
如果(scope.figures!==未定义){
for(设i=0;i
这是我的单元测试:
angular.module("myApp.directives")
.directive("test", ["$rootScope", function($rootScope) {
return {
restrict: "E",
scope: {
"figures": "="
},
templateUrl: "templates/components/test.html",
link: function(scope) {
scope.init = function() {
if (scope.figures !== undefined) {
for (let i = 0; i < scope.figures.length; i++) {
scope.figures[i].isModalVisible = false;
}
}
};
scope.init ();
}
};
}]);
describe("test", function () {
var element,
scope,
otherScope
mockData = [
{
isModalVisible: true
},
{
isModalVisible: false
}
];
beforeEach(angular.mock.module("myApp.directives"));
beforeEach(inject(function($rootScope, $compile) {
scope = $rootScope.$new();
scope.agg = mockData;
element = "<test figures=\"agg\"></test>";
element = $compile(element)(scope);
angular.element(document.body).append(element);
scope.$digest();
otherScope = element.isolateScope();
spyOn(otherScope, "init");
}));
//This one doesn't work
it("should close all modals by default", function () {
expect(otherScope.init).toHaveBeenCalled();
});
});
描述(“测试”,函数(){
var元素,
范围
其他范围
模拟数据=[
{
isModalVisible:对
},
{
isModalVisible:错误
}
];
在每个之前(angular.mock.module(“myApp.directions”);
beforeach(注入(函数($rootScope,$compile){
scope=$rootScope.$new();
scope.agg=模拟数据;
元素=”;
元素=$compile(元素)(范围);
元素(document.body).append(element);
范围。$digest();
otherScope=element.isolateScope();
spyOn(其他范围,“初始”);
}));
//这个不行
它(“默认情况下应关闭所有模态”,函数(){
expect(otherScope.init).tohaveBeenCall();
});
});
这是我当前遇到的错误:“预期已调用spy init。”首先:您的spyOn(scope,“init”)
和expect(scope,“init”)
都是在错误的作用域上执行的。您将initinside指令添加到隔离作用域中,因此它应该是spyOn(otherScope,“init”)
和expect(otherScope,“init”)
第二,第一点仍然会失败。:)原因是调用link()时只执行一次init(),这将发生在beforeach块内的scope.$digest()上,但其中不提供数据。您可以在测试中稍后提供它,因为指令已经在第一个摘要循环中链接,并且不会在测试中的第二个作用域上调用init()。$diget()
。为了解决这个问题,您需要将第一个摘要周期推迟到您在测试用例本身中准备好所有数据之后
第三,您需要首先将html元素附加到DOM中,然后才对其进行编译。在这种简单的情况下,它可能会工作,但如果元素中的任何内容需要父元素上的某个地方的指令(即,内部的指令具有类似require:“^something”
)的配置)然后编译将失败:在您将新元素插入DOM之前,没有包含新元素所需实体的父元素
更新
你不能像那样测试这个场景。安装spy的合适时间点应该是在将init()添加到作用域之后,但在调用它之前,但问题是该时间点位于指令内部,因为函数调用在将函数添加到作用域之后立即触发。因为这一点不在测试代码中,所以您没有机会以这种方式编写测试
但是让我们从另一个角度考虑这种情况。init()做什么?它会重置数据数组上的标志。因此,您可以在
$digest()
之前使用true
值初始化这些标志,并且可以在调用$digest()之后检查这些标志是否被重置。通过这种方式,您可以轻松准备数据并断言结果。您的测试将能够清楚地告诉您是否实际调用了init(),甚至更重要的是,它是否执行了它应该执行的操作。我根据您的说明成功地使第一部分正常工作,例如:this expect:expect(otherScope.figures[0]。isModalVisible)。toEqual(false);但是我的间谍无法工作。我已经在上面更新了我的代码,我昨天晚上做了,它成功了。我只是想再做一次检查,看看我的函数init在第一次调用指令时是否被调用fires@AngularM,这就是重点-您并不真正关心调用此函数的唯一事实。它可能被调用,但由于某种原因失败,或者您可以在将来更改实现,并且某些标志将阻止此重置周期运行。所以仅仅调用函数并不能告诉您任何有价值的事情。你真正关心的是它的工作是否完成了。