admin管理员组

文章数量:1023803

I have a JavaScript project which I want to observe the TDD methodology. I chose the karma framework and requirejs library for this and followed an example demonstrated in the karma docs here.

There is an example of one unit-test file, which is:

define(['app', 'jquery', 'underscore'], function(App, $, _) {

    describe('just checking', function() {

        it('works for app', function() {
            var el = $('<div></div>');

            var app = new App(el);
            app.render();

            expect(el.text()).toEqual('require.js up and running');
        });

        it('works for underscore', function() {
            // just checking that _ works
            expect(_.size([1,2,3])).toEqual(3);
        });

    });

});

The main problem with this approach is that there is no way to clear the App module for each test. So if there are some changes in the App (like closure variables changes etc.) in one it call, then they can affect other it call.

Could anyone suggest something on this? These are such popular tools, I can't believe no one ever ran into such a situation.

So, to recapitulate the question, I would like to ask for an answer for any of these more specific ones:

  • is there any way to "reset" (clear) module in requirejs? (actually, I suppose that there is no such a way, except reload all modules once again)
  • is there any better approach to run karma and requirejs, so that modules do not have any remains (side effects) of other tests (it function calls) on them ?

I have a JavaScript project which I want to observe the TDD methodology. I chose the karma framework and requirejs library for this and followed an example demonstrated in the karma docs here.

There is an example of one unit-test file, which is:

define(['app', 'jquery', 'underscore'], function(App, $, _) {

    describe('just checking', function() {

        it('works for app', function() {
            var el = $('<div></div>');

            var app = new App(el);
            app.render();

            expect(el.text()).toEqual('require.js up and running');
        });

        it('works for underscore', function() {
            // just checking that _ works
            expect(_.size([1,2,3])).toEqual(3);
        });

    });

});

The main problem with this approach is that there is no way to clear the App module for each test. So if there are some changes in the App (like closure variables changes etc.) in one it call, then they can affect other it call.

Could anyone suggest something on this? These are such popular tools, I can't believe no one ever ran into such a situation.

So, to recapitulate the question, I would like to ask for an answer for any of these more specific ones:

  • is there any way to "reset" (clear) module in requirejs? (actually, I suppose that there is no such a way, except reload all modules once again)
  • is there any better approach to run karma and requirejs, so that modules do not have any remains (side effects) of other tests (it function calls) on them ?
Share Improve this question asked Jan 18, 2015 at 15:25 d.kd.k 4,4702 gold badges32 silver badges41 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

With some help from Google I've found a solution to this. I cannot say that it is ideal, but it works at least and in each test a required module is in it's pristine state.

First, one need to have his main.js test file like this, it is almost the same as in the docs, except tests are not defined as modules and are not included as dependencies:

require.config({file
    baseUrl: '/base',
    paths: {},
    shim: {},
    deps: [],
    callback: window.__karma__.start
});

In the main karma config must be present this (one need to adapt his own paths)

files: [
    {pattern: 'src/**/*.js', included: false},
    'tests/unit/**/*.js'
],

And in the tests themselves we leverage jasmine async tests capabilities and requirejs.undef method for "clearing" a module (which will reset the loader's internal state to forget about the previous definition of the module, as it is stated in the docs).

This method has one implication, that it will not reset other modules, which are already loaded and depend on the reset module, but this should not be a problem, if one writes his tests in a right way, that is he tests only one module (and may be some parent ones, from which the child inherits some behavior), so that it should not be hard to undef several modules at ones.

describe('Some/Module tests', function() {
    'use strict'
    var M

    beforeEach(function(done) {
        requirejs.undef('src/Some/GParentModule')
        requirejs.undef('src/Some/ParentModule')
        requirejs.undef('src/Some/Module')
        require(['src/Some/Module'], function(m) {
            M = m
            done()
        })
    })

    it('some description', function() {
        var i = 0

        for (var prop in M) {
            i++
        }
        expect(i).toEqual(1)
        expect(prop).toEqual('init')
        expect(M.init).toEqual(jasmine.any(Function))
    })
})

I've checked this, between it calls changes to the module do not persist, so I suppose, it's safe to use this approach.

Thanks everyone for help, if someone has a better way, please answer here.

  • is there any way to "reset" (clear) module in requirejs?

You can use requirejs.undef(), but the documentation mention some gotchas. And to my knowledge there is no call you can use to say "unload this module and everything it depends on", which in a plex application is probably what is needed.

  • is there any better approach to run karma and requirejs, so that modules do not have any remains (side effects) of other tests (it function calls) on them ?

The better approach is to design your application so that state is tied to an object you instantiate rather than to the module itself. This is what I do in the test suite for a large application of mine. The beforeEach hook resets what requires resetting and instantiates the application anew for each test.

I have a JavaScript project which I want to observe the TDD methodology. I chose the karma framework and requirejs library for this and followed an example demonstrated in the karma docs here.

There is an example of one unit-test file, which is:

define(['app', 'jquery', 'underscore'], function(App, $, _) {

    describe('just checking', function() {

        it('works for app', function() {
            var el = $('<div></div>');

            var app = new App(el);
            app.render();

            expect(el.text()).toEqual('require.js up and running');
        });

        it('works for underscore', function() {
            // just checking that _ works
            expect(_.size([1,2,3])).toEqual(3);
        });

    });

});

The main problem with this approach is that there is no way to clear the App module for each test. So if there are some changes in the App (like closure variables changes etc.) in one it call, then they can affect other it call.

Could anyone suggest something on this? These are such popular tools, I can't believe no one ever ran into such a situation.

So, to recapitulate the question, I would like to ask for an answer for any of these more specific ones:

  • is there any way to "reset" (clear) module in requirejs? (actually, I suppose that there is no such a way, except reload all modules once again)
  • is there any better approach to run karma and requirejs, so that modules do not have any remains (side effects) of other tests (it function calls) on them ?

I have a JavaScript project which I want to observe the TDD methodology. I chose the karma framework and requirejs library for this and followed an example demonstrated in the karma docs here.

There is an example of one unit-test file, which is:

define(['app', 'jquery', 'underscore'], function(App, $, _) {

    describe('just checking', function() {

        it('works for app', function() {
            var el = $('<div></div>');

            var app = new App(el);
            app.render();

            expect(el.text()).toEqual('require.js up and running');
        });

        it('works for underscore', function() {
            // just checking that _ works
            expect(_.size([1,2,3])).toEqual(3);
        });

    });

});

The main problem with this approach is that there is no way to clear the App module for each test. So if there are some changes in the App (like closure variables changes etc.) in one it call, then they can affect other it call.

Could anyone suggest something on this? These are such popular tools, I can't believe no one ever ran into such a situation.

So, to recapitulate the question, I would like to ask for an answer for any of these more specific ones:

  • is there any way to "reset" (clear) module in requirejs? (actually, I suppose that there is no such a way, except reload all modules once again)
  • is there any better approach to run karma and requirejs, so that modules do not have any remains (side effects) of other tests (it function calls) on them ?
Share Improve this question asked Jan 18, 2015 at 15:25 d.kd.k 4,4702 gold badges32 silver badges41 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

With some help from Google I've found a solution to this. I cannot say that it is ideal, but it works at least and in each test a required module is in it's pristine state.

First, one need to have his main.js test file like this, it is almost the same as in the docs, except tests are not defined as modules and are not included as dependencies:

require.config({file
    baseUrl: '/base',
    paths: {},
    shim: {},
    deps: [],
    callback: window.__karma__.start
});

In the main karma config must be present this (one need to adapt his own paths)

files: [
    {pattern: 'src/**/*.js', included: false},
    'tests/unit/**/*.js'
],

And in the tests themselves we leverage jasmine async tests capabilities and requirejs.undef method for "clearing" a module (which will reset the loader's internal state to forget about the previous definition of the module, as it is stated in the docs).

This method has one implication, that it will not reset other modules, which are already loaded and depend on the reset module, but this should not be a problem, if one writes his tests in a right way, that is he tests only one module (and may be some parent ones, from which the child inherits some behavior), so that it should not be hard to undef several modules at ones.

describe('Some/Module tests', function() {
    'use strict'
    var M

    beforeEach(function(done) {
        requirejs.undef('src/Some/GParentModule')
        requirejs.undef('src/Some/ParentModule')
        requirejs.undef('src/Some/Module')
        require(['src/Some/Module'], function(m) {
            M = m
            done()
        })
    })

    it('some description', function() {
        var i = 0

        for (var prop in M) {
            i++
        }
        expect(i).toEqual(1)
        expect(prop).toEqual('init')
        expect(M.init).toEqual(jasmine.any(Function))
    })
})

I've checked this, between it calls changes to the module do not persist, so I suppose, it's safe to use this approach.

Thanks everyone for help, if someone has a better way, please answer here.

  • is there any way to "reset" (clear) module in requirejs?

You can use requirejs.undef(), but the documentation mention some gotchas. And to my knowledge there is no call you can use to say "unload this module and everything it depends on", which in a plex application is probably what is needed.

  • is there any better approach to run karma and requirejs, so that modules do not have any remains (side effects) of other tests (it function calls) on them ?

The better approach is to design your application so that state is tied to an object you instantiate rather than to the module itself. This is what I do in the test suite for a large application of mine. The beforeEach hook resets what requires resetting and instantiates the application anew for each test.

本文标签: javascripthow to reset a requirejs module between unit testsStack Overflow