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.