javascript 是否可以在函数内定义 Jasmine 规范并且仍然有 beforeEach 适用于它?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13139977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 17:55:02  来源:igfitidea点击:

Is it possible to define a Jasmine spec inside a function and still have beforeEach apply to it?

javascriptunit-testingjasmine

提问by Mark Stickley

I have a lot of tests which are virtually the same. In the interests of DRY and scanability I'd like to abstract the tests into a single function and then call that function with a few parameters. The function would then call itand add the spec to the suite.

我有很多几乎相同的测试。为了 DRY 和可扫描性,我想将测试抽象为单个函数,然后使用几个参数调用该函数。然后该函数将调用it规范并将其添加到套件中。

It seems to work, except the specs don't get run in the same way as the other specs and beforeEachis not called before the specs defined in the common function.

它似乎有效,除了规范的运行方式与其他规范不同,beforeEach并且不在公共函数中定义的规范之前调用。

define(['modules/MyModule','jasmine/jasmine'], function(MyModule) {

    describe('myModule', function() {

        function commonTests(params) {
            it('should pass this test OK', function() {
                expect(true).toBe(true);
            });

            it('should fail because module is undefined', function() {
                expect(module[params.method]()).toBe('whatever');
            });
        }

        var module;

        beforeEach(function() {
            module = new MyModule();
        });

        describe('#function1', function() {
            commonTests({
                method: 'function1'
            });
        });

        describe('#function2', function() {
            commonTests({
                method: 'function2'
            });
        });

    });

});

Is there any way of doing this and maintaining the functionality of beforeEachand afterEach?

是否有这样做的,维护的功能的任何方式beforeEachafterEach

UPDATE:

更新:

Looks like I got my example wrong, sorry. Here's the case that fails:

看起来我的例子错了,抱歉。这是失败的情况:

define(['modules/MyModule'], function(MyModule) {

    function commonTests(params) {
        it('will fail because params.module is undefined', function() {
            expect(typeof params.module).toBe('object');
            expect(typeof params.module[params.method]).toBe('function');
        });

        it('has a few tests in here', function() {
            expect(true).toBe(true);
        });
    }


    describe('MyModule', function() {

        var module;

        beforeEach(function() {
            module = new MyModule();
        });

        describe('#function1', function() {
            commonTests({
                module: module,
                method: 'function1'
            });
        });

        describe('#function2', function() {
            commonTests({
                module: module,
                method: 'function2'
            });
        });

    });
});

I think it fails because the value of moduleis preserved as part of the call to commonTestsinstead of always using the current value of moduleas in the first example. I'll post my solution when I get there...

我认为它失败了,因为 的值module被保留为调用的一部分,commonTests而不是module像第一个示例中那样始终使用当前值。当我到达那里时,我会发布我的解决方案......

采纳答案by Mark Stickley

Thanks to Andreas for pointing out that my first example actually worked! The final solution I'm using is very similar:

感谢 Andreas 指出我的第一个例子确实有效!我使用的最终解决方案非常相似:

define(['modules/MyModule'], function(MyModule) {

    var module;

    function commonTests(params) {
        it('will not fail because module is shared', function() {
            expect(typeof module).toBe('object');
            expect(typeof module[params.method]).toBe('function');
        });

        it('has a few tests in here', function() {
            expect(true).toBe(true);
        });
    }


    describe('MyModule', function() {

        beforeEach(function() {
            module = new MyModule();
        });

        describe('#function1', function() {
            commonTests({
                method: 'function1'
            });
        });

        describe('#function2', function() {
            commonTests({
                method: 'function2'
            });
        });

    });
});

Although if you needed to have the ability to pass in moduleas an argument to commonTestsyou would have to take a slightly different approach and have a different function for each itblock:

尽管如果您需要能够将module参数作为参数传递给commonTests您,则必须采用稍微不同的方法并为每个it块设置不同的函数:

define(['modules/MyModule'], function(MyModule) {

    var module;

    function commonTest1(params) {
        expect(typeof module).toBe('object');
        expect(typeof module[params.method]).toBe('function');
    }

    function commonTest2(params) {
        expect(true).toBe(true);
    }


    describe('MyModule', function() {

        beforeEach(function() {
            module = new MyModule();
        });

        describe('#function1', function() {

            it('will not fail because module is shared', function() {
                commonTest1({ method: 'function1' });
            });

            it('has a few tests in here', function() {
                commonTest2({ method: 'function1' });
            });

        });

        describe('#function2', function() {

            it('will not fail because module is shared', function() {
                commonTest1({ method: 'function2' });
            });

            it('has a few tests in here', function() {
                commonTest2({ method: 'function2' });
            });

        });

    });
});

This way the executions of the functions containing the common tests is delayed until after beforeEach has run its callback.

这样,包含公共测试的函数的执行会延迟到 beforeEach 运行其回调之后。

回答by Andreas

yes, this scenario works fine for us. We use chutzpah to run the the tests in our gated checkins and our tests would fail without the afterEachfunctions.

是的,这个场景对我们来说很好用。我们使用 chutzpah 在门控签入中运行测试,如果没有这些afterEach功能,我们的测试将失败。

But the defineline looks like require.js. We had several problems with that ... I suppose that MyModuleis undefinedor not defined as expected. Have you tried to set a breakpoint in the beforeEachmethod to see if it was called and what value MyModulehas? How are you calling the tests?

但这define条线看起来像require.js. 我们遇到了几个问题......我想这MyModule是否undefined按预期定义。您是否尝试在beforeEach方法中设置断点以查看它是否被调用以及MyModule具有什么值?你如何称呼测试?

When I run your code without the defineline the beforeEachfunction gets called 4x - as expected. Btw I used chutzpah.console.exe to call the tests.

当我在没有该define行的情况下运行您的代码时,该beforeEach函数被调用了 4 次 - 正如预期的那样。顺便说一句,我使用 chutzpah.console.exe 来调用测试。

Edit:

编辑:

Yeah, now I can reproduce the problem on my PC. And it's much more clear to me. At the beginning moduleis undefined as every variable is undefined first. Then you register your functions in jasmine using beforeEachand describe. Jasmine starts with evaluating

是的,现在我可以在我的 PC 上重现该问题。对我来说更清楚。开头module是未定义的,因为每个变量都是先未定义的。然后您使用beforeEach和在 jasmine 中注册您的函数describe。茉莉花从评估开始

function() {
    commonTests({
        module: module,
        method: 'function1'
    });
}

which was passed to the first describe. At the line module: moduleJS copies the referenceof var moduleto the new objects property moduleand this references undefinedso far. When the beforeEachcallback gets called it changes the reference of the var moduleto the correct value but the wrong reference has already been copied ...

传递给第一个describe. 在生产线module: moduleJS复制引用var module新对象属性module和该引用undefined至今。当beforeEach回调被调用时,它会将 的引用更改为var module正确的值,但错误的引用已被复制......

I tried to move var moduleabove function commonTestsand used that variable in the tests instead of params.moduleand they pass as expected. I don't know if that is an option in your environment but I hope it it helps.

我试图移动到var module上面function commonTests并在测试中使用该变量而不是params.module它们按预期通过。我不知道这是否适用于您的环境,但我希望它有所帮助。

Greets, Andreas

你好,安德烈亚斯