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

jest --watchAll fails when having test suites without mongodb mocking #445

Open
kerbe opened this issue Nov 25, 2023 · 0 comments
Open

jest --watchAll fails when having test suites without mongodb mocking #445

kerbe opened this issue Nov 25, 2023 · 0 comments

Comments

@kerbe
Copy link

kerbe commented Nov 25, 2023

I have growing codebase, where most early test suites were testing functions interacting with MongoDB, so all those tests needed MongoDB mocking to memory database. All went well up until that.

Now that I have tests suites in working that are about external API functionalities, those test APIs don't have MongoDB mocking in them. This is when problems started to arise.

When I run my test suite with either jest --watchAll or npm test -- --watchAll, initially all tests pass, as expected. But once I make any change to any file within project, most tests fail with following error:

 FAIL  __tests__/users/users.test.js
  ● Test suite failed to run

    ENOENT: no such file or directory, open '/home/user/path/to/my/project/globalConfig.json'

      at MongoEnvironment.setup (node_modules/@shelf/jest-mongodb/lib/environment.js:22:58)

Each test suite gives that same error. If I make new change, most likely similar errors occur again. Randomly few test suites might pass, while others give this same error. And really randomly, all tests suites might pass, as expected.
If I manually press enter in console where jest --watchAll is running, making it to rerun all tests, all tests pass once again.

I can prevent this error by adding MongoDB mocking lines to my non-database related test file, mainly these lines:

const { connect, disconnect } = require('../../lib/db/mongodb/mongodb');
jest.mock('../../lib/db/mongodb/mongodb');

And once those are present, jest --watchAll works as expected.

Another alternative is to use jest --onlyChanged --watch, which doesn't seem to be affected with this, even if there are both database related testsuites and non-database related testsuites present at same time.

To me this feels like a bug, but I can't really pinpoint exact cause/location for it. Another alternative is that I use this jest-mongodb package completely wrong, which causes this kind of behaviour.

Test files that have mongodb mocking have it done like this:

// __tests__/users/users.test.js
'use strict';

const { createUser } = require('../../lib/users');
const { connect, disconnect } = require('../../lib/db/mongodb/mongodb');

jest.mock('../../lib/db/mongodb/mongodb');

let db;
let collection;

beforeAll(async () => {
  // Mock the connection object
  db = await connect();
  collection = db.collection('users');
});

afterAll(async () => {
  // Close the MongoDB connection
  await disconnect();
});

describe('createUser', () => {
  it('should create new user to database', async () => {

    const newUser = {
      email: 'new@user.com',
      firstName: 'Sam',
      lastName: 'Sample',
    };

    const result = await createUser(newUser);

    const dbresult = await collection.findOne({ email: newUser.email });

    expect(result).toMatchObject(newUser);
  });
});

Here are related files:

// lib/db/__mocks__/mongodb.js
'use strict';

import { MongoMemoryServer } from 'mongodb-memory-server';
import { MongoClient, ObjectId } from 'mongodb';

const MONTHS_6 = 60 * 60 * 24 * 30 * 6;
const options = {
  useUnifiedTopology: true,
  useNewUrlParser: true,
};
let cachedDb = null;
let mongod = null;

let client;

export async function connect() {
  try {
    if (!mongod) {
      mongod = await MongoMemoryServer.create();
      const uri = await mongod.getUri();
      client = new MongoClient(uri, options);
      await client.connect();
      cachedDb = client.db('foobar');
    }
    return Promise.resolve(cachedDb);
  } catch (e) {
    console.error(`MONGO: ${e}`);
    return Promise.reject(e);
  }
}

export async function disconnect() {
  try {
    await client.close();
    await mongod.stop();
  } catch (e) {
    console.error(`MONGO: ${e}`);
  }
}

export async function collectionSelect(collection) {
  return cachedDb.collection(collection);
}
// jest.config.js
'use strict';

module.exports = {
  transform: {
    '^.+\\.(t|j)sx?$': '@swc/jest',
  },
  preset: '@shelf/jest-mongodb',
  watchPathIgnorePatterns: ['globalConfig'],
  restoreMocks: true,
  collectCoverageFrom: ['*.js', '*.ts', './lib/**/*.js', '!.eslintrc.js', '!*config.js'],
  setupFilesAfterEnv: ['<rootDir>/jestSetupTestEnvVars.js'],
};
// jest-mongodb-config.js
'use strict';

module.exports = {
  mongodbMemoryServerOptions: {
    binary: {
      version: '6.0.5',
      skipMD5: true,
    },
    autoStart: false,
    instance: {},
  },
};
// jestSetupTestEnvVars.js
'use strict';

const fs = require('fs');

(async () => {
  // Path to your .env.test file
  const envFilePath = '.env.test';

  // Read the contents of the .env.test file
  const lines = fs.readFileSync(envFilePath, 'utf8');
  lines.split(/\r?\n/).forEach((line) => {
    const [key, value] = line.split('=');
    if (key && value) {
      process.env[key] = value;
    }
  });
})();
// package.json dependecies
"devDependencies": {
    "@shelf/jest-mongodb": "^4.1.7",
    "@swc/core": "^1.3.52",
    "@swc/jest": "^0.2.26",
    "@types/jest": "^29.5.1",
    "@typescript-eslint/eslint-plugin": "^5.57.0",
    "esbuild": "^0.17.15",
    "eslint": "^8.38.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-config-airbnb-typescript": "^17.0.0",
    "eslint-plugin-import": "^2.27.5",
    "eslint-plugin-n": "^15.4.0",
    "jest": "^29.5.0",
    "jest-junit": "^16.0.0",
    "mongodb-memory-server": "^8.12.2",
  },
  "dependencies": {
    "mongodb": "^5.3.0",
  }

Any help would be greatly appreciated.

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

No branches or pull requests

1 participant