meteor/guide

Testing stubbing

lorensr opened this issue · 4 comments

we show how to mock a template helper and stub functions with simon, but what about an object? for a global object, this doesn't work:

// foo-bar.test.js
Foo = {} // attempting to mock Foo
import 'foo-bar.js'
...

// foo-bar.js
Foo.bar = () => {...};

// foo.js (not included in the test)
Foo = {...}

gives ReferenceError: Foo is not defined in foo-bar.js.

and what if it wasn't a global and foo-bar.js imported Foo – how do you mock an import?

I think in both cases you'd need to import foo.js in order to mock it.

In pure ES2015 import land, foo-bar.js is doing:

import Foo from 'foo'; // 1
Foo.bar = ...

So your test would need to do

import Foo from 'foo';
// stub Foo's props
import 'foo-bar';

Or use a require-mocker like Jest to make line // 1 act differently. Unfortunately things like Jest aren't really possible in Meteor right now, because of our non-standard require system, AFAICT.

In Meteor linker-land, line // 1 is implicit, so it's more confusing.

Thanks! So no way currently to mock Foo itself, right? Like if this worked (doesn't b/c Foo is a const):

import Foo from './foo.js';
Foo = {test: 'stubbed'}
import './foo-bar.js'

What about adding this to the "Stubbing" part of the unit test section:

If you're testing code that makes use of globals from outside the imports/ directory, you'll need to import those globals. For instance if you have a global Todos collection and are testing this file:

// logging.js
export const function logTodos() {
  console.log(Todos.findOne());
}

then you'll need to import Todos both in that file and in the test:

// logging.js
import { Todos } from './todos.js'
export const function logTodos() {
  console.log(Todos.findOne());
}
// logging.test.js
import { Todos } from './todos.js'
Todos.findOne = () => { 
  return {text: "write a guide"}
}

import { logTodos } from './logging.js'
// then test logTodos
...

That seems great @lorensr