theKashey / rewiremock

The right way to mock dependencies in Node.js or webpack environment.
MIT License
492 stars 30 forks source link

mockThroughByDefault plugin doesn't preserve classes #120

Closed kataik closed 4 years ago

kataik commented 4 years ago

Let's say I have a module I'd like to mock, which exports a class definition and a function as default:

function foo(): string {
  return 'foo';
}

class Bar {
  public field: string = 'bar';
  public bar() {
    return 'bar';
  }
}

export default foo;
export { Bar };

When using the mockThroughByDefault plugin, it translates the exported class Bar into a constructor function which constructs an empty object. If I remove the plugin and call callThrough() directly, it works as expected:

import rewiremock, { addPlugin, plugins } from 'rewiremock';
import * as dependency from './dependency';

addPlugin(plugins.mockThroughByDefault); // to make it work, comment this line

async function execute() {
  rewiremock(() => require('./dependency'))
    // .callThrough() // to make it work, uncomment this line
    .withDefault(() => 'mock');

  rewiremock.enable();
  const mod: typeof dependency = require('./dependency');
  rewiremock.disable();

  console.dir(mod);
  const bar = new mod.Bar();
  console.dir(bar);
  console.info(bar.field);
  console.info(bar.bar());
}

execute().then(() => console.info('done'));

Again, if I replace the plugin with callThrough(), it yields (as expected):

{ default: [Function], Bar: [Function: Bar] } Bar { field: 'foo' } foo foo  done

Test project: https://repl.it/repls/HeavyProfuseMaps

theKashey commented 4 years ago

Standard mockFactory creates empty functions. Just mocks. You might need to use more smart something, like sinon.spy or jest-mock - there is function to provide default implementation - .stubFactory

See example of usage - https://github.com/theKashey/rewiremock/blob/b13cd4b19660b6cb4570919b27a27450c63e97b1/_tests/mock.spec.js#L359-L364

Why

Because you probably want to use stubs/spies and expectations provided by your framework, and I don't know what are they.

kataik commented 4 years ago

Thanks for the quick response. I actually did not expect it to define mocks/stubs for me, I do that separately. I was expecting it to implicitly add .callThrough() to all .with(..) and .withDefault(..) calls.

Did I misunderstood the purpose of the plugin?

theKashey commented 4 years ago

Probably. There are 3 behaviors:

The default mode is the first one - do nothing you haven't asked for explicitly.

kataik commented 4 years ago

My bad, thanks for explaining! Great library!