Unit Testing and Mocking in Jest in Meteor 1.8

#1

I’m looking to add unit tests and mocking to my existing code base on Meteor 1.8 uing Jest and maybe even React Testing Framework.

I don’t see many complete examples of mocking things like a Mongo (‘meteor/mongo’) collection or a Meteor method (‘meteor/meteor’) for example.

My setup:

package.json

  "devDependencies": {
    "faker": "^4.1.0",
    "jest": "^24.7.1",
    "meteor-jest-stubs": "^1.8.0"
  }

jest.config.js

module.exports = {
    transform: {
      '^.+\\.jsx?$': 'babel-jest',
    },
    moduleFileExtensions: [
      'js',
      'jsx',
    ],
    modulePaths: [
      '<rootDir>/node_modules/',
      '<rootDir>/node_modules/meteor-jest-stubs/lib/',
    ],
    unmockedModulePathPatterns: [
      '/^imports\\/.*\\.jsx?$/',
      '/^node_modules/',
    ],
    modulePathIgnorePatterns: [
        ".meteor"
    ]
  };

If I run jest --watch the following code fails

mongo.test.js

const Mongo = require('meteor/mongo')
const accounts = new Mongo.Collection("accounts");

function getDependentCounts() {
  
}


it('first mongo test', () => {
  const dependentCounts = getDependentCounts(); /*?*/

  expect(dependentCounts).toBe(0)
});

Error:

TypeError: Mongo.Collection is not a constructor

      1 | 
      2 | const Mongo = require('meteor/mongo')
    > 3 | const accounts = new Mongo.Collection("accounts");
        |                  ^
      4 | 
      5 | function getDependentCounts() {

I understand that I need to mock this Mongo call, and I have not done so yet. But doesn’t Jest even have the capability to pull in ‘meteor/mongo’ and actually make a call to MongoDB? How are we suppose to do integration testing at some point?

And when I add a Collection mock:

Add a mock directory and a mapper to resolve

    moduleNameMapper: {
      "^meteor/(.*)": "<rootDir>/.mocks/$1.js"
    },

Mock the collection

const Collection = jest.fn();
Collection.prototype.attachSchema = jest.fn();
Collection.prototype.insert = jest.fn();
Collection.prototype.update = jest.fn();
Collection.prototype.remove = jest.fn();
Collection.prototype.findOne = jest.fn();
Collection.prototype.find = jest.fn(() => ({
  count: jest.fn(),
  fetch: jest.fn(),
}));
Collection.prototype.helpers = jest.fn();
Collection.prototype.before = {
  insert: jest.fn(),
  update: jest.fn(),
};
Collection.prototype.after = {
  insert: jest.fn(),
  update: jest.fn(),
};
const Mongo = { Collection };

const RemoteCollectionDriver = jest.fn();
RemoteCollectionDriver.prototype.open = jest.fn().mockReturnThis();
RemoteCollectionDriver.prototype.insert = jest.fn();
RemoteCollectionDriver.prototype.update = jest.fn();
RemoteCollectionDriver.prototype.remove = jest.fn();
RemoteCollectionDriver.prototype.findOne = jest.fn();
RemoteCollectionDriver.prototype.find = jest.fn(() => ({
  count: jest.fn(),
  fetch: jest.fn(),
}));
const MongoInternals = { RemoteCollectionDriver };

module.exports = {
  Mongo,
  MongoInternals,
};

I get this error:

Configuration error:
    
    Could not locate module meteor/accounts-base mapped as:
    /Users/aadams/Meteors/development/fp-client/.mocks/accounts-base.js.
    
    Please check your configuration for these entries:
    {
      "moduleNameMapper": {
        "/^meteor\/(.*)/": "/Users/aadams/Meteors/development/fp-client/.mocks/$1.js"
      },
      "resolver": null
    }

      at createNoMappedModuleFoundError (node_modules/jest-resolve/build/index.js:471:17)
          at Array.reduce (<anonymous>)
      at SearchSource.findRelatedTests (node_modules/@jest/core/build/SearchSource.js:280:30)
      at SearchSource.findTestRelatedToChangedFiles (node_modules/@jest/core/build/SearchSource.js:363:14)