How to reset a requirejs module between unit tests

I have a JavaScript project that I want to observe on the TDD methodology. I chose karma karma and the requirejs library for this and followed the example shown in the karma docs here .

Example of a single unit test file:

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 application module for each test. Therefore, if there are some changes in the application in the application (for example, changes to closing variables, etc.) in one call to it , they can affect another call to it .

Can anyone suggest anything about this? These are such popular tools, I can’t believe that no one has encountered such a situation.

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

  • Is there a way for the reset (clear) module in requirejs? ( in fact, I believe that there is no such method, with the exception of rebooting all the modules again )
  • Is there any better approach to run karma and requirejs, so that the modules do not have any leftovers (side effects) of other tests ( it function calls) on them?
+5
source share
2 answers

With some help from Google, I found a solution to this. I can’t say that it is perfect, but it works at least, and in each test the required module is in it intact.

Firstly, you need to have a test file main.js , like this, it is almost the same as in docs , except for tests that are not defined as modules and are not included as dependencies:

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

This should be present in the main configuration of karma (you need to adapt your own paths)

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

And in the tests themselves, we use the capabilities of asynchronous jasmine tests and the requirejs.undef method to "clean up" the module (which will reset the internal state of the bootloader to forget about the previous module definition, as indicated in docs ).

This method has one implication that it will not reset other modules that are already loaded and depend on the reset module, but this should not be a problem if you write its tests correctly, that is, it checks only one module (and there may be some parent , from which the child inherits some behavior), so it should not be difficult to undef several modules in them.

 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 checked this, between it change calls are not saved in the module, so I believe it is safe to use this approach.

Thank you all for your help, if anyone has a better way, answer here.

+3
source
  • Is there a way for the reset (clear) module in requirejs?

You can use requirejs.undef() , but some gotchas are mentioned in the documentation. And as far as I know, there is no call that you can use to say β€œunload this module and everything it depends on”, which is probably necessary in a complex application.

  • Is there any better approach to run karma and requirejs, so that the modules do not have any residuals (side effects) of other tests (these are function calls) on them?

The best approach is to design your application so that the state is bound to the object you are creating, and not to the module itself. This is what I am doing in the test suite for a large application of mine. The beforeEach hook resets what needs to be reset and starts the application again for each test.

+1
source

Source: https://habr.com/ru/post/1211365/


All Articles