Global `before` and `beforeEach` for mocha?
JavascriptUnit Testingmocha.jsJavascript Problem Overview
I'm using mocha for javascript unit-testing now.
I have several test files, each file has a before
and beforeEach
, but they are exactly the same.
How do I provide a global before
and beforeEach
for all of them (or some of them)?
Javascript Solutions
Solution 1 - Javascript
In the root of the test folder, create a global test helper test/helper.js
which has your before and beforeEach
// globals
global.assert = require('assert');
// setup
before();
beforeEach();
// teardown
after();
afterEach();
Solution 2 - Javascript
from the mocha documentation… > ## ROOT-LEVEL HOOKS > > You may also pick any file and add “root”-level hooks. For example, > add beforeEach() outside of all describe() blocks. This will cause the > callback to beforeEach() to run before any test case, regardless of > the file it lives in (this is because Mocha has an implied describe() > block, called the “root suite
All regular describe()
-suites are first collected and only then run, this kinda guarantees this being called first.
'use strict'
let run = false
beforeEach(function() {
if ( run === true ) return
console.log('GLOBAL ############################')
run = true
});
Remove the run-flag, if you want to see it run each time, before every test.
I named this file test/_beforeAll.test.js
. It has no need to be imported/required anywhere, but the .test.
(resp. .spec.
) in the filename is important, so that your testrunner picks it up…
mocha.opts
\o/
bonus track 8-): using If there's stuff, you truly only want to set up once before running your tests (regardless which ones...), mocha.opts
is a surprisingly elegant option! – Just add a require
to your file (yes, even if it contributes little to mocha, but rather to your test setup). It will run reliably once before:
( in this example I detect, if a single test or many tests are about to run. In the former case I output every log.info()
, while on a full run I reduce verbosity to error+warn... )
Update:
If someone knows a way, to access some basic properties of the mocha suite that is about to be run in once.js
, I would love to know and add here. (i.e. my suiteMode
-detection is lousy, if there was another way to detect, how many tests are to be run…)
Solution 3 - Javascript
Declare a before
or beforeEach
in a separate file (I use spec_helper.coffee
) and require it.
spec_helper.coffee
afterEach (done) ->
async.parallel [
(cb) -> Listing.remove {}, cb
(cb) -> Server.remove {}, cb
], ->
done()
test_something.coffee
require './spec_helper'
Solution 4 - Javascript
I've had similar issue when I needed to "mock" global variables used by one of dependencies.
I used .mocharc.js for that, since code in that JS file is being executed once when "mocha" environment is being setup.
Example .mocharc.js:
global.usedVariable = "someDefinedValue";
/** other code to be executed when mocha env setup **/
module.exports = {};
This worked for me, nevertheless this looks quite "dirty" way to do that. Please, comment if you know a better place for that code :)
Solution 5 - Javascript
mochaHooks
root hook plugin minimal example on Mocha 8
This mechanism is currently documented at: https://mochajs.org/#root-hook-plugins
It does not work for before
, only for beforeEach
however, since before
is not in the list of available hooks from: https://mochajs.org/#available-root-hooks
Here's a demo:
test/global.js
// Root hook.
exports.mochaHooks = {
beforeEach(done) {
console.log('mochaHooks.beforeEach');
done();
},
};
// Bonus: global fixture, runs once before everything.
exports.mochaGlobalSetup = async function() {
console.log('mochaGlobalSetup');
};
test/mytest.js
var assert = require('assert');
describe('describe0', function() {
// Only runs before the current describe.
before(async () => {
console.error('before describe 0');
});
beforeEach(async () => {
console.error('beforeEach describe 0');
});
it('it 0 0', function() {
assert.equal(0, 0);
});
it('it 0 1', function() {
assert.equal(0, 0);
});
describe('describe 0 0', function() {
before(async () => {
console.error('before describe 0 0');
});
beforeEach(async () => {
console.error('beforeEach describe 0 0');
});
it('it 0 0 0', function() {
assert.equal(0, 0);
});
it('it 0 0 1', function() {
assert.equal(0, 0);
});
});
describe('describe 0 1', function() {
before(async () => {
console.error('before describe 0 1');
});
beforeEach(async () => {
console.error('beforeEach describe 0 1');
});
it('it 0 1 0', function() {
assert.equal(0, 0);
});
it('it 0 1 1', function() {
assert.equal(0, 0);
});
});
});
Then you enable that file with --require
:
npx mocha --require test/global.js test/
Outcome:
mochaGlobalSetup
describe0
before describe 0
mochaHooks.beforeEach
beforeEach describe 0
✓ it 0 0
mochaHooks.beforeEach
beforeEach describe 0
✓ it 0 1
describe 0 0
before describe 0 0
mochaHooks.beforeEach
beforeEach describe 0
beforeEach describe 0 0
✓ it 0 0 0
mochaHooks.beforeEach
beforeEach describe 0
beforeEach describe 0 0
✓ it 0 0 1
describe 0 1
before describe 0 1
mochaHooks.beforeEach
beforeEach describe 0
beforeEach describe 0 1
✓ it 0 1 0
mochaHooks.beforeEach
beforeEach describe 0
beforeEach describe 0 1
✓ it 0 1 1
6 passing (6ms)
So we see that the global hook ran before every local beforeEach
.
For before
I couldn't find a better solution than defining a helper and calling it from every before
: https://stackoverflow.com/questions/28191243/how-can-i-make-mocha-load-a-helper-js-file-that-defines-global-hooks-or-utilitie
Tested on mocha 8.3.2, Node v14.16.0.
Solution 6 - Javascript
The use of a modules can make it easier to have a global setup/teardown for your test suite. Here is an example using RequireJS (AMD modules):
First, let's define a test environment with our global setup/teardown:
// test-env.js
define('test-env', [], function() {
// One can store globals, which will be available within the
// whole test suite.
var my_global = true;
before(function() {
// global setup
});
return after(function() {
// global teardown
});
});
In our JS runner (included in mocha's HTML runner, along the other libs and test files, as a <script type="text/javascript">…</script>
, or better, as an external JS file):
require([
// this is the important thing: require the test-env dependency first
'test-env',
// then, require the specs
'some-test-file'
], function() {
mocha.run();
});
some-test-file.js
could be implemented like this:
// some-test-file.js
define(['unit-under-test'], function(UnitUnderTest) {
return describe('Some unit under test', function() {
before(function() {
// locally "global" setup
});
beforeEach(function() {
});
afterEach(function() {
});
after(function() {
// locally "global" teardown
});
it('exists', function() {
// let's specify the unit under test
});
});
});