Giter VIP home page Giter VIP logo

mock-require's People

Contributors

andrewmash avatar boblauer avatar fuqcool avatar jorgenevens avatar jormarma avatar josh-egan avatar mightyiam avatar mingos777 avatar minrwhite avatar patrickdawson avatar tiagomapmarques avatar tyriar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mock-require's Issues

Does this also work with Es2015 ?

I'm trying to use this library, but so far it doesn't seem to work.

I've created a test repo for this
If you run the code, the original function is still executed.

Any help would be appreciated!

Mocking a module with constructor

Hi,

I'm trying to mock-require the js-ubersmithclient module, however it uses a constructor, like this:

const Ubersmith = require('js-ubersmithclient')
let ubersmithClient = new Ubersmith(url, username, password)

And then you can actually use the various functions that the API provides, e.g.:

ubersmith.uber.check_login({login: username, pass: password})
.then(...)

(where uber.check_login is just what the API provides, and not part of the module itself).

Is there any way that mock-require can mock that sort of constructor and the subsequent API calls?

Thank you.

Ability to mock missing deps.

My use case requires me to support two behaviors, one for one a module exists and one if it's, missing. I tried to use this module to write the test suite for both scenarios but this:

mock({
  './hello.json': { foo: 'bar' }
})

require('./hello.json')

yields

Error: Cannot find module './hello.json'
  at Function.Module._load (node_modules/mock-require/index.js:24:22)
  at require (internal/module.js:20:19)
  at Context.it.only (index.test.js:32:5)

Is this a missing feature or I am missing something?

mock.stopAll()

It would be nice if there was a possibility to stop mocking all modules with a single call:

mock.stopAll();

or similar.

The rationale behind my request is that I often have multiple mocks in dozens of test cases and it's annoyingly repetitive to add the afterEach in every single test case with all the mocks I have created. Instead, it would be much cleaner to just create a single afterEach call after every test in the entire test suite (Jasmine allows this), reducing greatly the amount of boilerplate code:

var mock = require("mock-require");
afterEach(function() {
    mock.stopAll();
});

I can provide a pull request if needed.

Not mocking package under Jest

Hi and thanks for this package, it seems really useful. Specially since there are some packages that cannot be mocked easily otherwise.

I am trying an example very similar to the one stated in the documentation:

var mock = require('mock-require');

mock('pkg-dir', { sync: function () {
  console.log('pkg.sync() called');
}});

const pkg = require('pkg-dir');
console.log(pkg.sync());

When I try it with Node.js with node plugins/index.test.js (in my case) it works flawlessly printing pkg.sync() called. However, with Jest (with slight modifications since at least one test is required) it does not seem to work:

var mock = require('mock-require');

mock('pkg-dir', { sync: function () {
  console.log('pkg.sync() called');
}});

it('is synced', () => {
  const pkg = require('pkg-dir');
  console.log(pkg.sync());
});

It prints the directory where the package.json is hosted, as the pkg-dir library specifies (so it runs the original code). I have no idea how to even debug this since it seems like it's an issue with Jest + mock-require. I do not know the differences at runtime of Node.js and Jest, I thought Jest just loaded a couple of functions like it() and expect() but otherwise used a stock Node.js runtime.

How to use mock-require with execa?

First of all, thanks for a great module!

I'm trying to use mock-require with execa, but unfortunately the mock doesn't run.

Here is the gist of my test:

const mock = require('mock-require');
const execa = require('execa');

mock('analyze-deps', './analyze-deps-mock');

it('should ...', () => {
  return expect(execa('./bin/deps'))
    .to.eventually.have.property('stdout').equal('something');
});

where ./bin/deps is simply:

#!/usr/bin/env node

require('../index');

With this setup, ./analyze-deps-mock is not run.

If I replace execa('./bin/deps') with require('../index'), then ./analyze-deps-mock is run as expected.

I assume the problem is that execa spawns a new process, but not sure how to workaround this.

Any ideas?


To reproduce:

  1. git clone [email protected]:moroshko/analyze-deps-cli.git
  2. cd analyze-deps-cli
  3. git checkout 93251ff
  4. npm install
  5. npm test

The mocked module is still loaded

The module which I'm trying to mock refers to global variables which do no exist in my node environment. I'd like that module to be not loaded at all, but simply mocking it with mock('myModule', {}); still makes it (and its imports as well) to be loaded. Is there a way to just not load that module?

mock-require not always called with Mocha

I'm mocking some libraries using mock-require in my unit tests. I'm using Mocha 3.1.2 and Node 4.7.0. I have my tests in the folder test in separate files. Running mocha test/foo.js works perfectly, but running npm test (which in turn runs mocha --reporter spec test/*.js) makes the same tests in test/foo.js fail! To be exact, the require statements sometimes still return the real libraries, not the mocked ones.

I inserted some debugging statements in mock-require, especially in the overridden Module._load function, and it seems like that function is not being called for all require statements. For example: if the file test/foo.js requires src/bar.js(using the correct path of course) and that file requires src/libAsdf.js, then the overridden Module._load is correctly called when requiring src/bar.js but NOT when requiring src/libAsdf.js. This is always the pattern: mock-require works for the first link in a require chain, but not after that.

NOTE: This only happens when running mocha on all my tests. Running individual test files, mock-require is correctly used for all files in the dependency tree.

I couldn't spot any obvious answer to this problem, I suppose it's some magic that Mocha does. Any tips?

Introduce a changelog and version tags

It's not easy to learn what new features or fixes landed with given version updates, or even more importantly what were breaking changes with given major (is it safe for me to upgrade or not?)

There seems to be no changelog, no release notes, and when one wants to look into code of specific version it's impossible on Github due to lack corresponding tags

reRequiring index files returns startMocking

When trying to reRequire a file named index that is in the local path, reRequire will instead return what mock-require exports, specifically the startMocking function.

Example code:

index.js:

const fs = require('fs')
// ...
module.exports = { fs }

test.js:

const mock = require('mock-require')

mock('fs', {})

const index = mock.reRequire('./index')

console.log(index)

Expected output:

{ fs: {} }

Actual output:

function startMocking(path, mockExport) {
  const calledFrom = getCallerFile();

  if (typeof mockExport === 'string') {
    mockExport = getFullPathNormalized(mockExport, calledFrom);
  }

  pendingMockExports[getFullPathNormalized(path, calledFrom)] = mockExport;
}

Based on looking at the code (and specifically at getFullPath and isInNodePath, it looks like any file that can be resolved from the mock-require package will cause it to return that file rather than the actual local file.

Issue with mock path

Hi @boblauer,

I have the following project structure:

  • lib
    • gtm.js
    • setEnvironment.js
  • spec
    • unit
      • gtm.spec.js

gtm.js:

var setEnvironment = require('./setEnvironment');
module.exports = function() {
  setEnvironment();
}

gtm.spec.js:

// ....
var gtm = require('../../lib/gtm');

var setEnvironment = jasmine.createSpy();
mock('./setEnvironment', setEnvironment);

gtm();

mock.stopAll();
// ....

The problem is that when I run the code above, mock-require doesn't mock ./setEnvironment path. I went deeper and debug it a little bit. When mock('./setEnvironment', setEnvironment); is run:

  1. startMocking called with ./setEnvironment, Function arguments
  2. getFullPath called with ./setEnvironment, /vagrant/spec/unit/gtm.spec.js arguments
  3. resolvedPath = require.resolve(path); throws Error: Cannot find module './setEnvironment'

Please confirm is that bug or not? If not, could you please let me know about any possible workaround?

travis ci

Travis Ci does not seem to work with mock requires the same as what I have locally, is there anything that could cause mock require not to work in their environment?

This probably isn't really an issue with mock require but I figured it would be best to open one in case others run into the same problem

Mocking Nested Dependencies

Hello,

I'm having trouble mocking nested dependencies in my Jasmine tests. Here is the code:

mockSpec.js

'use strict';

const mock = require('mock-require');

describe('mock', function() {
    mock('./test', 'MOCKED');

    var testSubject = require('./subfolder');

    it("should be mocked", function() {
        expect(testSubject.test).toBe("MOCKED");
    })

    mock.stopAll();
})

subfolder/index.js

'use strict';

module.exports = {
    test: require('./test')
}

subfolder/test.js

'use strict';

module.exports = 'ORIGINAL';

I would expect this test to pass but instead it fails:

Failures:
1) mock should be mocked
  Message:
    Expected 'ORIGINAL' to be 'MOCKED'.

I also tried using mock.reRequire() as well as making the require paths relative to the spec file without success.

Very good!

This is one module which can mock React modules, resolve paths, don't launch original dependencies, etc. Thanks!

Unexpected Behaviour

Hi,

I'm aware that mocking via object key replacement doesn't necessarily work, i.e

const module = require('...')
const { feature } = module;

and

exports = function () { }

Don't work with sinon and similar libraries. This led me to mock-require.

I've been playing with it using before() and after() in mocha and individual unit tests complete successfully, however since tests are not sandbox there is module mock creep and others fail. Resolving this has been surprisingly difficult. I have concluded that reRequire() in before/after suffers the same flaw as the others because mocha enumerates all the describe() functions before running the if functions, so unless all tests have their requires inside the before and after they will be loaded immediately.

I have a solution, but it is yet to work and I believe this is a bug with mock--require.

mock.reRequire('./payment'); // just in case
mock.reRequire('../../../../common/daoFactory'); // just in case
const getOneByQuery = () => Promise.resolve(null);
mock('../../../../common/daoFactory', () => {
    return {
        getOneByQuery
    };
});
const payment = require('./payment'); // immediately requires and calls daoFactory.
mock.stopAll();
mock.reRequire('./payment');
mock.reRequire('../../../../common/daoFactory');

Here two modules are removed from node cache (just in case). The mock is inserted and the main unit loaded. It references the mock. I don't think mock.stopAll() is necessary unless it's firing event emitters as reRequire() should do the same thing. Unlike using after() subsequent spec files loaded by mocha will reference the require module. Mocks are changed by modifying the function in this case.

Alas it doesn't work as expected, the daoFactory still references the require module. Is mock() async in any way? I can't see what else it could be.

`caller.getTypeName is not a function`

This module is exactly what I'm looking for, but when I imported it and ran it, I got this runtime error. Any ideas what's happening here? I'm running on Node v8.

/workspace/node_modules/caller-id/lib/caller-id.js:12
        typeName: caller.getTypeName(),
                         ^

TypeError: caller.getTypeName is not a function
    at Object.getData (/workspace/node_modules/caller-id/lib/caller-id.js:12:26)
    at startMocking (/workspace/node_modules/mock-require/index.js:27:29)
    at Object.<anonymous> (/workspace/tests/test.js:3:1)
    at Module._compile (module.js:624:30)
    at Object.Module._extensions..js (module.js:635:10)
    at Module.load (module.js:545:32)
    at tryModuleLoad (module.js:508:12)
    at Function.Module._load (module.js:500:3)
    at Module.require (module.js:568:17)
    at require (internal/module.js:11:18)
    at /Users/mcphandr/.nvm/versions/node/v8.6.0/lib/node_modules/mocha/lib/mocha.js:231:27
    at Array.forEach (<anonymous>)
    at Mocha.loadFiles (/Users/mcphandr/.nvm/versions/node/v8.6.0/lib/node_modules/mocha/lib/mocha.js:228:14)
    at Mocha.run (/Users/mcphandr/.nvm/versions/node/v8.6.0/lib/node_modules/mocha/lib/mocha.js:514:10)
    at Object.<anonymous> (/Users/mcphandr/.nvm/versions/node/v8.6.0/lib/node_modules/mocha/bin/_mocha:480:18)
    at Module._compile (module.js:624:30)
    at Object.Module._extensions..js (module.js:635:10)
    at Module.load (module.js:545:32)
    at tryModuleLoad (module.js:508:12)
    at Function.Module._load (module.js:500:3)
    at Function.Module.runMain (module.js:665:10)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:607:3

mocking nested dependencies

Consider this test:

subject:

const dep = require('./dep');

module.exports = () => {
    return dep();
}

dep:

const uuid = require('uuid/v4');

module.exports = () => {
    return uuid();
}

test:

const t = require('tap');
const mock = require('mock-require');

let subject = require('./subject');

t.test('should return uuid', t => {
  mock('uuid/v4', () => '12345');
  subject = mock.reRequire('./subject');

  const result = subject();

  t.equal(result, '12345');
  t.end();
});

This test fails because the nested uuid/v4 dependency is not actually mocked. Why is that and how can I make it work? What am I missing here?

Cannot get to work with an express route module

I am trying to mock a dependency in a route module in an express js server but cannot get it to work.
I tried everything with the route module loaded in the main server/index.js file so I thought ok just remount the route on another root path so to have two paths to the routes with different prefixes like when you version an end point but this one will be for testing with the mocked service/business layer module which is called ecourier.controller in my sample. See below but even then on the new /apitest route path it still does not mock the Module.... AWWWWWW..

Please what am I doing wrong...

import chai from 'chai';
import server from '..';

var mock = require('mock-require');

chai.use(require('chai-http'));

var expect = chai.expect;

var route = '/apitest/shipmentDispatched';

var mockreq = null;

var winstoncls = {
stream: {
write: (msg) => { console.log(msg); }
}
}

const emptycls = { name: 'Dummy class' };

mock('../controllers/ecourier.controller', {
updateDispatch: function(res,req,config) {
res.json({ status: 'OK' });
}
});

mock.reRequire('../controllers/ecourier.controller');

import routes from '../routes';

server.use('/apitest', routes({ emptycls, emptycls, emptycls, winstoncls }));

Use normalize() for consistency in Windows

The method getFullPath() does not take into consideration Win32 environments with mixed Posix style require strings.

For instance:

mockRequire(process.cwd() + "/" + path, obj);

In Posix environment the backslash remains, but in Win32 environment, the backslash becomes a forward slash "".

To overcome, wrap the result of getFullPath() with a call to normalize(), exposed by the path module.

mocking nested dependencies

I believe this issue is similar to #34 , but unfortunately when I tried the suggested solution by @boblauer it did not work. I've tried to include slightly more specific code in case I misunderstood issue #34 and my situation is in fact different.

server file (subject)

const express = require('express')
const app = express()

// import route
const router = require('./route')
app.use('/', router)

const startServer = () => {
  app.listen(PORT, () => logger.info('Listening on port 3000'))
}

startServer()

module.exports = app

router file (dep)

const express = require('express')
const router = express.Router()

// Import function
const { getTwilio } = require('./utils')
const twilioClient = getTwilio()

const routeFunction(req, res) {
  twilioClient.messages.create({
      body: 'xxxx,
      messagingServiceSid: 'xxxx',
      from: 'xxxx',
      to: 'xxxx',
    })
}

router.post('/',  routeFunction)

utils function dependency

function getTwilio () {
  return require('twilio')(process.env.ACCOUNT_SID, process.env.AUTH_TOKEN)
}

module.exports = {
  getTwilio,
}

test file

const chai = require('chai')
const chaiHttp = require('chai-http')
chai.use(chaiHttp)
const sinon = require('sinon')
const mock = require('mock-require')

// Mock twilio client
const twilioStub = sinon.stub()
const twilioStub = () => ({
  messages: {
    create: twilioStub,
  },
})
mock('./utils', { getTwilio: twilioStub })

// Import server
const server = require('./index')

async function tests () {
  describe('tests', () => {
        mock.reRequire('./route')
        server = mock.reRequire('./index')
        const res = await chai
          .request(server)
          .post('/')
          .send()
        const resBody = JSON.parse(res.text) 
  })
}

As it stands, if I do not use:

mock.reRequire('./route')
server = mock.reRequire('./index')

the dependency is not mocked and the actual dependency is used instead, even though the mock was created before I imported the server file. Anyone has any idea why this is happening?

Support for Unix wildcards

Is there a way to use unix wildcards?

Something like so: mock('*.scss');. I think this would be useful if you want to mock CSS modules for unit testing.

It may be a stupid suggestion, but I thought it was worth sharing it.

Module._load alignment with Node

I noticed that mock-require doesn't align with Node in its Module._load overwrite in that it requires parent (even though parent may be null or undefined). See the Node version for more. This caused an error with a combo of nyc, mock-require, and @std/esm packages.

How to mock requires inside an imported module?

Hi,

I'm using Jasmine to test a helper module that contains a few requires. I have tried to use the reRequire method, but it does not seem to do the trick:

beforeEach(function () {
    mock('mime', { lookup: function () {
      return 'application/sadsda'
    }})

    helper = mock.reRequire('./helper')}

When I test a method in the helper module, I can see that the actual modules are being used, rather than the mocks. Am I doing something wrong?

Thank you.

Impossible to return strings

Hi,
I am currently having the issue where I want to mock a HTML-file. Unfortunately, I cannot do this because if the second argument of mock() is a string, it assumes that it is a path to look for a module to return. But I simply want mock('../templates/template.html', 'dummytemplate') to return 'dummytemplate'.
Maybe this is already possible somehow...?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.