为什么嵌套的 describe() 块看不到外部块中定义的变量?

2022-01-11 00:00:00 jasmine javascript

我在实际代码中遇到过这个问题,但我整理了一个简单的例子来证明这一点.

I've run into this issue in real code, but I put together a trivial example to prove the point.

以下代码可以正常工作.我在我的根 describe() 块中设置了一个变量,该变量可在我的 sub-describe()s' it() 中访问块.

The below code works fine. I've set up a variable in my root describe() block that is accessible within my sub-describe()s' it() blocks.

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/

但是,如果我尝试通过执行以下操作来稍微干掉我的代码,它就会中断:

However, if I try to DRY up my code a little by doing the following, it breaks:

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() 块中定义的.

Within the nested describe() scope, the orchard object is undefined, even though it's defined within the it() blocks within it.

这是否是 Jasmine 的开发人员有意为之,可能是为了避免在 beforeEach() 中重置对象的问题以及可能破坏一些引用?他们如何做到这一点?我可以看到这可能很有用,我只是很好奇它是如何工作的.(我的猜测是一些 apply()call() 魔术,但我不确定如何......)

Is this intentional on the part of Jasmine's developers, possibly to avoid issues with resetting the object in beforeEach() and possible breaking some references? How do they make it happen? I could see how this might be useful, I'm just very curious as to how it works. (My guess is some apply() or call() magic, but I'm not sure how...)

--

作为旁注,我仍然可以通过简单地使用另一个 beforeEach() 块来干掉我的代码:

As a side-note, I can still DRY up my code by simply using another beforeEach() block:

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 块之前执行.要解决这个问题,第三个代码片段是唯一的方法.

The body of a describe block is executed before the beforeEach blocks.

This is exactly as expected. The problem is that your var trees variable is trying to access orchard before it has been initialized. The body of a describe block is executed before the beforeEach blocks. To solve this problem, the third code snippet is the only way to go.

Jasmine 将首先执行 describe 块,然后在运行每个测试之前执行 beforeEach 块.

Jasmine will first execute the describe blocks, and then execute the beforeEach blocks before running each test.

相关文章