Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Squire.js not substituting fake dependency when using store

I'm trying out Squire.js as a dependency loader for RequireJS. Using a totally normal web browser for running unit tests. I want to use store to get a handle to my mocks. But can't stop Squire loading the actual module.

mock works fine:

define(['lib/squire'], function (squire) {
    var injector = new squire();

    injector
    .mock('modules/dependency', {
        run: function () {
            console.log("fake dependency run");
        }
    })
    .require(['modules/module-under-test'], function (module) {
        module.run();
    });
});

Console output

module under test loaded       module-under-test.js:2
module under test run          module-under-test.js:5
fake module run                module-test.js:8

But when I use store like this:

define(['lib/squire'], function (squire) {
    var injector = new squire();

    injector
    .store('modules/dependency')
    .require(['modules/module-under-test', 'mocks'], function (module, mocks) {
        mocks.store["modules/dependency"] = {
            run: function () {
                console.log("fake dependency run");
            }
        };
        module.run();
    });
});

The real one is used and run:

real dependency loaded      dependency.js:2
module under test loaded    module-under-test.js:2
module under test run       module-under-test.js:5
real dependency run         dependency.js:5

Squire says on the front page of the docs that this is ok to do. Using latest version of Squire.js from Github, and also latest RequireJS from requirejs.org. What am I doing wrong?

like image 774
sennett Avatar asked Oct 02 '22 10:10

sennett


1 Answers

I don't see where you are calling run in the second example but I will assume it is after the assignment to mocks.store["modules/dependency"].

I think the issue here is that you are attempting to stub the entire dependency, rather than just the run method. This approach works in the first case because the dependency has not yet been resolved. In the second case, module-under-test already has its reference to dependency. So replacing the copy that Squire has 'stored' does nothing. I believe the correct manner of using store would be as follows:

mocks.store["modules/dependency"].run = function () {
    console.log("fake dependency run");
};

In short, if you want to replace the entire dependency then that is what mock is for. Store only allows you to stub individual properties of the dependency before they are accessed by the code under test. (So if the code under test were to invoke run upon load, rather than when invoked by the test, you would still need to use mock.)

There is an alternative approach, for cases where use-upon-load forces you to use mock yet you only want to stub a few properties on the value that the dependency would otherwise resolve to. First require the dependency at the same time the you require Squire. Stub the methods you need stubbed. Then use mock to have Squire to use your partially stubbed dependency when resolving the dependencies for the module under test. In your case, this would look like:

define(['lib/squire', 'modules/dependency'], function (squire, dep) {
    var injector = new squire();

    dep.run = function () {
        console.log("fake dependency run");
    };

    injector
    .mock('modules/dependency', dep)
    .require(['modules/module-under-test'], function (module) {
        module.run();
    });
});
like image 191
Kenneth Baltrinic Avatar answered Oct 07 '22 19:10

Kenneth Baltrinic