theKashey/rewiremock

Consider adding context around examples

RodeoChuck opened this issue · 3 comments

Context like what you are mocking and the use of the mock in test code. There are several important details that are made ambiguous with this:

 const file = rewiremock.proxy('file.js', {
   'dependency':  stub
 });

What is 'dependency' other than a string? How is it used?

What is stub? like a sinon.stub()?

what is in file.js and how does 'dependency' related to 'stub'?

I'm familiar with proxyuire and am looking to do something simple like:

const { rewiremock } = require('../../../../tests/rewiremock');
const { sinon } = require('sinon');
const updateItem = sinon.stub();
const updateItemAdmin = rewiremock.proxy('../updateItemAdmin', { 
    updateItem: updateItemStub // wanting to mock the dependency updateItem that updateItemAdmin uses
});

However if I run into a problem with an ambiguous symptom I'm left guessing if I assumed correctly that updateItem: updateItemStub is the correct usage.

rewiremock.proxy is an implementation of proxyquire interface. If you are familiar with proxyquire - you should be familiar with .proxy*

  • that is true only if relative plugin is active
  • file.js is proxy target, a file to require and return from the rewiremock.proxy
  • dependency is another module to mock. By default it is just a string, if node plugin is active, then it should be path to a real file, relative to the current file (not a test target!)
  • What is 'dependency' other than a string? it could be a function. In this case the expectation is that that function will require/import real file underneath. This feature was added to type stubs, and not available in .proxy interface. Just because {} is not able to store function key.
  • What is stub? It could be anything you want to replace a dependency with.
const updateItem = sinon.stub(); 
// ^^this^^ is incorrect. It should be a pointer to another module.
const updateItemAdmin = rewiremock.proxy('../updateItemAdmin', { 
    updateItem: updateItemStub // wanting to mock the dependency updateItem that updateItemAdmin uses
});

So, let's start from the scratch - what is updateItem inside updateItemAdmin?

updateItemAdmin will end up calling one of its dependencies (that is accesses via a require in its implementation file). I want to replace that dependency with a spy function using rewiremock.proxy().

So I have:

const updateItemSpy = sinon.spy(); 
const updateItemAdmin = rewiremock.proxy('../updateItemAdmin', { 
    updateItem: updateItemSpy 
});

and end up doing asserts like:

sinon.assert.calledWith(updateItemSpy, sinon.match('email', 'jdoe@this.net'));

Problem I'm running into is that within ../updateItemAdmin I can tell that the updateItem dependency is the stock one and not the one I'm attempting to proxy. I must be reading the example wrong and thats why having context code around these rewiremock-specific parts would help.

The problem manifests it self by sinon complaining that "sinon.spy() is not stubbed" but if my use of rewiremock.proxy above were correct I can't see any difference from this simple example on sinonjs's website:

"test should assert fuzzy": function () {
    var book = {
        author: "cjno"
    };
    var spy = sinon.spy();

    spy(book);

    sinon.assert.calledWith(spy, sinon.match({ author: "cjno" }));
}

The only other oddity that could be at play is the need to add ".default" to the otherwise example rewiremock.js config:

// rewiremock.cjs.js
const rewiremock = require('rewiremock'); 
// nothng more than `plugins.node`, but it might change how filename resolution works
/// settings
rewiremock.overrideEntryPoint(module);
// and all stub names would be a relative
rewiremock.addPlugin(rewiremock.plugins.relative);
//rewiremock.addPlugin(rewiremock.plugins.usedByDefault);
module.exports = rewiremock.default;

if you use common.js - then you need to use .default. In any other case(Babel/ESM, TypeScript) - you don't have to.