The purpose of this article is to describe the behavior of
the beforeAll
and beforeEach
functions in a Jasmine spec.
beforeAll
and beforeEach
,
along with afterAll
and afterEach
, are Jasmine global
functions that can be used manage expensive setup and
teardown in test suites.
The beforeAll
function executes once and
only once for the
describe
block containing it,
before any of the beforeEach
functions or any of the specs.
The beforeEach
function executes before any spec
in the describe
block
containing it, as well as before any spec contained inside
any inner describe
. You'll see this in
A More Complex Example below.
beforeAll
has a complementary function in
afterAll
that is run once per describe
after all specs contained therein are finished.
Likewise, the beforeEach
function has a complementary
afterEach
function that is run after each spec.
afterAll
and afterEach
are used for
whatever cleanup is needed
at the conclusion of the specs, and are not covered as
part of this document.
Consider the following test file. Notice that there is one describe
,
one beforeAll
, one beforeEach
, and two
specs, i.e., it
functions, with a console.log
in each.
describe('A single describe', function() {
beforeAll(function() {
console.log('in beforeAll');
});
beforeEach(function() {
console.log('in beforeEach');
});
it('spec A', function() {
console.log('in spec A');
expect(true).toBe(true);
});
it('spec B', function() {
console.log('in spec B');
expect(true).toBe(true);
});
});
Running the above test produces the following output:
log: in beforeAll log: in beforeEach log: in spec A log: in beforeEach log: in spec B
Notice the beforeAll
was called one time and the beforeEach
was called
once before each it
.
Now let's increase the complexity of the test. Notice the following
test has two describe
blocks, one inside the
other, with each describe
containing a beforeAll
, beforeEach
, and two
it
functions.
describe('Outer describe', function () {
beforeAll(function () {
console.log('in outer beforeAll');
});
beforeEach(function () {
console.log('in outer beforeEach');
});
it('spec A', function () {
console.log('in spec A');
expect(true).toBe(true);
});
it('spec B', function () {
console.log('in spec B');
expect(true).toBe(true);
});
describe('inner describe', function () {
beforeAll(function () {
console.log('in inner beforeAll');
});
beforeEach(function () {
console.log('in inner beforeEach');
});
it('spec C', function () {
console.log('in spec A');
expect(true).toBe(true);
});
it('spec D', function () {
console.log('in spec B');
expect(true).toBe(true);
});
});
});
Running the above test produces the following output:
log: in outer beforeAll log: in outer beforeEach log: in spec A log: in outer beforeEach log: in spec B log: in inner beforeAll log: in outer beforeEach log: in inner beforeEach log: in spec C log: in outer beforeEach log: in inner beforeEach log: in spec D
Carefully observe the results. Notice that the 'outer' beforeAll
was executed only once, as we expected, and the 'inner' beforeAll
was also executed once, but after the two 'outer' specs.
But look at the beforeEach
. For spec A
and spec B, only the outer beforeEach
was fired before those tests. However, for spec C
and spec D, both the
'outer' and 'inner' beforeEach
are fired before each
of those specs.
Knowing the difference between beforeAll
and
beforeEach
allows the programmer
to not only optimize the tests by placing setup code in a
beforeAll
or a beforeEach
as needed,
but provides the added benefit DRYing up duplicated setup
code. Understanding when the beforeAll
and
beforeEach
functions
are called in relation to each other and within nested
describe blocks provides opportunities for success, but lack
of understanding provides opportunities for confusing failure.
One word of caution however. Use the afterAll
and afterEach
properly to ensure state is not leaked between specs.