Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How To Mock Dependencies For Testing? #366

Closed
micahasmith opened this issue Mar 2, 2015 · 19 comments
Closed

How To Mock Dependencies For Testing? #366

micahasmith opened this issue Mar 2, 2015 · 19 comments

Comments

@micahasmith
Copy link

I was wondering how to mock a module's dependency for a test?

For instance, let's say that I have a module A that references another module B, but for my unit test I want module B to be swapped out with a fake-- can I do that with systemjs? (esp with es6 modules)

Wasn't able to find any info online. Thanks!

@matthewp
Copy link
Contributor

matthewp commented Mar 2, 2015

System.map["moduleB"] = "fake/moduleB";

@micahasmith
Copy link
Author

sweet. so just do that before importing the module and its all good?

also, does it keep these fake dependencies within the scope of one test file? anything i should know about "resetting"/"clearing out" the fakes?

@guybedford
Copy link
Member

You can "swap out" dependencies with something like:

System.set('custom/module', System.newModule({ custom: 'module' }));
var tmp = System.get('custom/module');
System.set('custom/module', ...); // etc

@micahasmith
Copy link
Author

Both of these means don't work for me:

https://github.com/micahasmith/babel-test/blob/master/test/app.test.js#L15-L47

@guybedford
Copy link
Member

I take it you're swapping out dependencies of the module you're importing? If so note you need to System.delete the index.js module by exact name as well as both dependencies before re-importing to get the right effect.

@micahasmith
Copy link
Author

thanks! going to test now

@micahasmith
Copy link
Author

Doesn't work for me either:

https://github.com/micahasmith/babel-test/blob/master/test/app.test.js#L50-L96

Is there some other way devs are going about this now? (Am i using an antiquated solution to code isolation via dep swapping?)

@guybedford
Copy link
Member

It could be worth ensuring the delete operation is returning true to indicate its actually doing something. Note you need to be using SystemJS 0.15 with the fix from ModuleLoader/es-module-loader#313.

@micahasmith
Copy link
Author

its in there in both of the new tests, System.delete("src/index");

@guybedford
Copy link
Member

Yes - but check it is returning true just like var p = {a: 'value'} delete p.b returns false unless p.b exists.

@guybedford
Copy link
Member

Actually delete doesn't do that, but System.delete does...

@micahasmith
Copy link
Author

Yep, returns true

@guybedford
Copy link
Member

And you're definitely using SystemJS 0.15?

@micahasmith
Copy link
Author

i npm installed jspm yesterday, it was version v0.14

it included systemjs v0.13.2

even if i upgrade and get this fixed though, it'll only lead into the problem that the systemjs loader is based on a global mutable singleton map of dependencies, which means i would have to enforce order/non-async execution of my tests in order to ensure that while i mutate the System.js config for one test its not trying to import/use that config in another test, correct?

or does System.js have a means to mutate within a sandbox/context?

@guybedford
Copy link
Member

Right, the SystemJS update for jspm that will make this work is coming tomorrow or Friday (working on it).

If you want to create a custom version of SystemJS for testing, you can use System.clone() which will create a new loader for you. You still need to run config on it after cloning though.

@micahasmith
Copy link
Author

Awesome. Well i'm super excited to try both after the release.

I'll check back in on this next week then. Thanks!

@onlywei
Copy link

onlywei commented Feb 4, 2016

After some trial and error, I finally got this working. I had to call System.normalizeSync() on all paths, otherwise they didn't work.

let functionToTest;

beforeEach((done) => {
  System.delete(System.normalizeSync('foo/bar.js'));
  System.set(System.normalizeSync('foo/bar.js'), System.newModule({...});

  System.delete(System.normalizeSync('foo/functionToTest.js'));
  System.import('foo/functionToTest.js').then((imported) => {
    functionToTest = imported;
  }).then(done, fail);
});

I think it's kind of weird that I have to do this, because System.normalizeSync() is not an advertised method in any API docs. @guybedford I'm not sure if this is intentional. I think a sensible default for System.delete() might be to automatically call System.normalizeSync() internally if the initial attempt didn't delete anything? What do you think?

@guybedford
Copy link
Member

@onlywei that is exactly correct.

@onlywei
Copy link

onlywei commented Feb 5, 2016

@guybedford should the normalizeSync() method be displayed in the System API docs, or do you have a vision to simplify this API for mocking?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants