Velocity Meteor Stubs compatibility with import { Meteor } from 'meteor/meteor' syntax

Is there a way to get the MeteorStubs package to work in this context:

Unit under test:

import { Meteor } from 'meteor/meteor';

class Component {

	constructor() {
		
		Meteor.startup(() => {
			
			this.$initialize.apply(this,[]);

		});

	}


	$initialize() {

		this.$onInit();

	}

	$onInit() {

	}

}

export { Component, Component as default };

test:

import { expect } from "meteor/practicalmeteor:chai";
import { sinon } from "meteor/practicalmeteor:sinon";
import { MeteorStubs } from "meteor/velocity:meteor-stubs";
import { Meteor } from "meteor/meteor";
import Component from './component';

describe('Component', () => {

	let myComponent;

	class TestComponent extends Component {

		constructor() {
		
			super();
		
		}

		$onInit() {

		}

	}

	beforeEach(() => {

		MeteorStubs.install();

	});

	afterEach(() => {
		
		MeteorStubs.uninstall();

	});

	describe('constructor', () => {
		
		it('should register a startup function with meteor.', () => {

			myComponent = new TestComponent();

			let spy = sinon.spy(myComponent, '$onInit');

			Meteor.runStartupMethods();

			expect(spy.called).to.be.true;

		});

	});


});

The problem I have is that since my unit under test explicitly import Meteor from the package, the MeteorStubs don’t seem to get installed onto that context. So I end up getting the error that Meteor.runStartupMethods() is not a function. I’m aware that MeteorStubs.install accepts a context parameter, but I’m not sure there is an appropriate context to pass in there. This test works fine if I remove the Meteor import statements and just refer to global.Meteor.

Any thoughts welcome!

Mocking objects while using ES2015 modules can definitely be a pain. Here’s a quick unit testing hack I use to mock Meteor:

  1. /imports/utility/core/meteor.js
import * as core from 'meteor/meteor';

let Meteor;
if (!core.Meteor.isTest) {
  Meteor = core.Meteor;
} else {
  const meteorStubs = require('meteor/velocity:meteor-stubs').MeteorStubs;
  const stubContext = {};
  meteorStubs.install(stubContext);
  Meteor = stubContext.Meteor;
}

export default Meteor;
  1. Change any
import { Meteor } from 'meteor/meteor';

statements to

import Meteor from '/imports/utility/core/meteor.js';

This avoids touching the Meteor global (not that I’m using it but just in-case), and the mocked Meteor object is used in any file that has this import (while in test mode).

Again, this is a quick hack - there are much better/capable solutions out there, most of which provide require dependency injection.

1 Like

Not a bad way to hack it! Thanks for the tip.