In the following example we want to run tests on the User
class.
We could instantiate const user = new User()
in every test (and for such a simple example it might be cleaner).
But in real apps there can be a lot of setup code before each test.
So in this example before each test we create a fresh User
instance (in beforeEach()
).
Without this, the isActive
or email
properties will leak from a previous test into the next test.
We are using beforeEach()
which runs before every test()
or it()
.
There is also beforeAll()
, which runs once per describe scope (or globally) before any test()
or it()
in that scope runs (see notes on nesting below).
class User {
constructor(name, email) {
this.name = name;
this.email = email;
this.isActive = true;
}
deactivate() {
this.isActive = false;
}
updateEmail(newEmail) {
this.email = newEmail;
}
}
describe('User class tests', () => {
let user;
beforeEach(() => {
user = new User(
'Bob',
'bob@example.com'
);
});
test('should create user with correct initial values', () => {
expect(user.name).toBe('Bob');
expect(user.email).toBe(
'bob@example.com'
);
expect(user.isActive).toBe(true);
});
test('should deactivate user account', () => {
user.deactivate();
expect(user.isActive).toBe(false);
});
test('should update user email', () => {
user.updateEmail(
'newemail@example.com'
);
expect(user.email).toBe(
'newemail@example.com'
);
});
});
beforeAll
- per describe()
scope (or global) - runs once before any test in that scope
beforeEach
- runs before each test - parent beforeEach
also runs for nested describe()
blocks
afterEach
- runs after each test - runs from inner to outer in nested describe()
blocks
afterAll
- per describe()
scope (or global) - runs once after all tests in that scope
We covered describe()
blocks in a previous lesson, to help organise your tests.
They are also used to control the following:
- A
beforeAll
/afterAll
within a describe()
block will run before/after running tests within that describe block
- A
beforeEach
/afterEach
within a describe()
block will only run before/after tests within that describe block
Here is an example:
beforeAll(() => {});
describe('nested level 1', () => {
describe('nested level 2 - a', () => {
beforeEach(() => {});
test('some test', () => {});
test('another test', () => {});
describe('nested level 3', () => {
test('a third test', () => {});
});
});
describe('another describe block', () => {
test('a test', () => {});
});
});
Lesson Task
Add a beforeEach(() => {...})
which sets calculator = new Calculator
, so that when the test runs there is a new instance of the Calculator class for the test to use.