为什么嵌套的 describe() 块不能看到在外部块中定义的变量
Why can't nested describe() blocks see vars defined in outer blocks?
我在实际代码中遇到了这个问题,但我整理了一个微不足道的例子来证明这一点。
下面的代码工作正常。我已经在我的根describe()
块中设置了一个变量,可以在我的子describe()
it()
块中访问。
describe('simple object', function () {
var orchard;
beforeEach(function () {
orchard = {
trees: {
apple: 10,
orange : 20
},
bushes: {
boysenberry : 40,
blueberry: 35
}
};
});
describe('trees', function () {
it ('should have apples and oranges', function() {
var trees = orchard.trees;
expect (trees.apple).toBeDefined();
expect (trees.orange).toBeDefined();
expect (trees.apple).toEqual(10);
expect (trees.orange).toEqual(20);
});
it ('should NOT have pears or cherries', function() {
var trees = orchard.trees;
expect (trees.pear).toBeUndefined();
expect (trees.cherry).toBeUndefined();
});
});
});
http://jsfiddle.net/w5bzrkh9/
但是,如果我尝试通过执行以下操作稍微干涸我的代码,它会中断:
describe('simple object', function () {
var orchard;
beforeEach(function () {
orchard = {
trees: {
apple: 10,
orange : 20
},
bushes: {
boysenberry : 40,
blueberry: 35
}
};
});
describe('trees', function () {
var trees = orchard.trees; // TypeError: Cannot read property 'trees' of undefined
it ('should have apples and oranges', function() {
expect (trees.apple).toBeDefined();
expect (trees.orange).toBeDefined();
expect (trees.apple).toEqual(10);
expect (trees.orange).toEqual(20);
});
it ('should NOT have pears or cherries', function() {
expect (trees.pear).toBeUndefined();
expect (trees.cherry).toBeUndefined();
});
});
});
http://jsfiddle.net/goqcev42/
在嵌套describe()
范围内,orchard
对象是未定义的,即使它是在其中的it()
块中定义的。
这是 Jasmine 开发人员的故意,可能是为了避免在 beforeEach()
中重置对象并可能破坏某些引用的问题? 他们是如何实现的?我可以看到这可能有什么用,我只是很好奇它是如何工作的。(我的猜测是一些apply()
或call()
魔法,但我不确定如何......
--
作为旁注,我仍然可以通过简单地使用另一个beforeEach()
块来干掉我的代码:
describe('simple object', function () {
var orchard;
beforeEach(function () {
orchard = {
trees: {
apple: 10,
orange : 20
},
bushes: {
boysenberry : 40,
blueberry: 35
}
};
});
describe('trees', function () {
var trees;
beforeEach(function() {
trees = orchard.trees;
});
it ('should have apples and oranges', function() {
expect (trees.apple).toBeDefined();
expect (trees.orange).toBeDefined();
expect (trees.apple).toEqual(10);
expect (trees.orange).toEqual(20);
});
it ('should NOT have pears or cherries', function() {
expect (trees.pear).toBeUndefined();
expect (trees.cherry).toBeUndefined();
});
});
});
describe
块的主体在beforeEach
块之前执行。
这完全符合预期。问题是您的var trees
变量在初始化之前正在尝试访问orchard
。describe
块的主体在beforeEach
块之前执行。 为了解决这个问题,第三个代码片段是唯一的方法。
Jasmine 将首先执行描述块,然后在运行每个测试之前执行 beforeEach 块。
您仍然可以初始化 beforeEach 块之外的变量。我通常为常量这样做,并且仍然保持干燥,而无需在之前引入每个块。
describe('simple object', function () {
const orchard = {
trees: {
apple: 10,
orange: 20
},
bushes: {
boysenberry: 40,
blueberry: 35
}
};
describe('trees', function () {
const trees = orchard.trees;
it('should have apples and oranges', function () {
expect(trees.apple).toBeDefined();
expect(trees.orange).toBeDefined();
expect(trees.apple).toEqual(10);
expect(trees.orange).toEqual(20);
});
it('should NOT have pears or cherries', function () {
var trees = orchard.trees;
expect(trees.pear).toBeUndefined();
expect(trees.cherry).toBeUndefined();
});
});
});
让我们看第三个代码片段。此外,它可以重构如下:
describe('simple object', function () {
var orchard;
beforeEach(function () {
orchard = {
trees: {
apple: 10,
orange : 20
},
bushes: {
boysenberry : 40,
blueberry: 35
}
};
});
describe('trees', function () {
it ('should have apples and oranges', function() {
expect (orchard.trees.apple).toBeDefined();
expect (orchard.trees.orange).toBeDefined();
expect (orchard.trees.apple).toEqual(10);
expect (orchard.trees.orange).toEqual(20);
});
it ('should NOT have pears or cherries', function() {
expect (orchard.trees.pear).toBeUndefined();
expect (orchard.trees.cherry).toBeUndefined();
});
});
});
对于茉莉花的新人,这就是你如何理解上面的代码:''
-
describe
定义了一个test suite
。这里的test suite
名称是用户定义的简单字符串,比如"简单对象"。 test suite
本身可以包含其他test suites
,这意味着describe
可以包含嵌套套件。- 就像其他编程语言一样,
orchid
对测试套件中定义的所有函数和套件都是全局的simple object
。 -
It
块称为specification
或SPEC
。It
块包含单个测试。 - 就在
Jasmine
执行测试用例时,它将首先访问it
块,这意味着它将遍历所有it
块声明。 - 当
Jasmine
实际执行测试用例时,它将检查beforeEach
函数,因此orchard
获取分配给它trees
值。 因此,您无需在
sub suite
内编写 beforeEach 函数。你可以简单地忽略beforeEach (function(( { trees = orchard.trees; }(;
现在将下面的最新代码段与上面的第三个代码段进行比较。
- 如何在定义js文件后为外部javascript文件设置变量
- 像createComment这样的各种自定义变量名在内联javascript中被覆盖,但在外部js中没有.为什么?
- 定义函数时,如何捕获外部变量的当前值
- Rally SDK外部开发Rally环境未定义
- 函数从$(document).ready外部调用在$(document).ready中定义的函数
- JavaScript未定义的函数外部JavaScript文件
- 取消重置由外部样式表定义的样式
- JavaScript-如何将onload函数内部定义的变量取到外部
- 异步.js瀑布(在数组外部定义的函数)
- 为什么使用函数构造函数创建的 Javascript 函数无法访问在其外部定义的其他函数
- 在构造函数内部和外部定义公共方法之间有什么区别吗?
- 如何将参数传递给在表单标记外部定义的 javascript 函数
- JavaScript 在函数外部定义变量
- 使用回调函数更改 getJSON 外部定义的变量的值
- 可以't从套接字连接外部定义的方法发出
- 如何对调用外部定义的库函数的Javascript文件进行单元测试?
- JS/使用在函数外部定义的对象
- 从外部定义的函数访问作用域中的变量
- 在它外部定义的对话框中的 var 返回未定义的 jQuery
- 在函数内部和外部定义变量的区别