Using NodeJS and Mocha for testing. I think I understand how before() and beforeEach() work. Problem is, I'd like to add a setup script that runs before each "describe" rather than before each "it".
If I use before()
it will run only once for the entire suite, and if I use beforeEach()
it will execute before every single test, so I'm trying to find a middle ground.
So, if this is my test file:
require('./setupStuff');
describe('Suite one', function(){
it('S1 Test one', function(done){
...
});
it('S1 Test two', function(done){
...
});
});
describe('Suite two', function(){
it('S2 Test one', function(done){
...
});
});
I'd like to have "setupStuff" contain a function that runs before 'Suite one' and 'Suite two'
Or, in other words, before 'S1 Test one' and 'S2 Test one' but NOT before 'S1 Test two'.
Can it be done?
There's no call similar to beforeEach
or before
that does what you want. But it is not needed because you can do it this way:
function makeSuite(name, tests) {
describe(name, function () {
before(function () {
console.log("shared before");
});
tests();
after(function () {
console.log("shared after");
});
});
}
makeSuite('Suite one', function(){
it('S1 Test one', function(done){
done();
});
it('S1 Test two', function(done){
done();
});
});
makeSuite('Suite two', function(){
it('S2 Test one', function(done){
done();
});
});
you can also do it in this more flexible way:
require('./setupStuff');
describe('Suite one', function(){
loadBeforeAndAfter(); //<-- added
it('S1 Test one', function(done){
...
});
it('S1 Test two', function(done){
...
});
});
describe('Suite two', function(){
loadBeforeAndAfter();//<-- added
it('S2 Test one', function(done){
...
});
});
describe('Suite three', function(){
//use some other loader here, before/after, or nothing
it('S3 Test one', function(done){
...
});
});
function loadBeforeAndAfter() {
before(function () {
console.log("shared before");
});
after(function () {
console.log("shared after");
});
}
I have found this approach worked for me, it patches all describe suites.
function suitePatches()
{
before(function()
{
// before suite behaviour
});
after(function()
{
// after suite behaviour
});
}
let origDescribe = describe;
describe = function(n,tests)
{
origDescribe(n,function()
{
suitePatches();
tests.bind(this)();
});
}
let origOnly = origDescribe.only;
describe.only = function(n,tests)
{
origOnly(n,function()
{
suitePatches();
tests.bind(this)();
});
}
describe.skip = origDescribe.skip;
Differences from the other answers are:
- The use of
bind
to call the tests
which ensures that if they call functions on this
, such as this.timeout(1000)
will still work.
- Handling
.skip
and .only
means that you can still use those on your suite, eg describe.skip
to temporarily suppress suites.
- Replacing the
describe
function by name allows for a less intrusive injection.
- This may not be to everyone's taste, in which case obviously an alternative function name can be used whilst still making use of the correct handling of calling the
tests
and only
and skip
.