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

时间:2012-10-30 13:24:02

标签: javascript unit-testing jasmine

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

它似乎有效,除了规范不会像其他规范那样运行,并且在公共函数中定义的规范之前没有调用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'
            });
        });

    });

});

有没有办法做到这一点并维护beforeEachafterEach的功能?

更新:

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

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'
            });
        });

    });
});

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

2 个答案:

答案 0 :(得分:5)

感谢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'
            });
        });

    });
});

虽然如果你需要能够将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' });
            });

        });

    });
});

这样,包含常见测试的函数的执行被推迟到beforeEach运行其回调之后。

答案 1 :(得分:0)

是的,这种情况对我们来说很好。我们使用chutzpah在我们的门禁签入中运行测试,如果没有afterEach函数,我们的测试将失败。

define行看起来像require.js。我们有几个问题...... 我认为MyModuleundefined或未按预期定义。您是否尝试在beforeEach方法中设置断点以查看它是否已被调用以及MyModule具有什么值?你是怎么称呼考试的?

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

编辑:

是的,现在我可以在我的电脑上重现这个问题了。而且对我来说更清楚了。 在开头module未定义,因为每个变量都是未定义的。然后使用beforeEachdescribe在茉莉花中注册您的函数。 Jasmine从评估开始

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

传递给第一个describe。在第module: module行,JS将var module引用复制到新对象属性module,此引用到目前为止undefined。调用beforeEach回调后,它会将var module的引用更改为正确的值,但错误的引用已被复制...

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

电贺, 安德烈亚斯