When a test mixes setup, behavior, and verification, it becomes harder to read. The Arrange-Act-Assert (AAA) pattern gives every test a simple, uniform layout: prepare the conditions, run the behavior, and check the result. section 2.12 section 2.5.1
Separate the test into three deliberate phases:
- Arrange: create the system under test and its dependencies, such as a fake rule that returns a known result. section 2.12 section 2.5.1
- Act: call the method under test with the prepared input and capture its output. section 2.12
- Assert: verify that the output matches the expected behavior, such as an error containing the fake rule’s reason. section 2.12 section 2.5.1
A small AAA test
test('reports the rule reason', () => { // Arrange const fakeRule = input => ({ passed: false, reason: 'fake reason' }); const verifier = new PasswordVerifier(); verifier.addRule(fakeRule); // Act const errors = verifier.verify('any value'); // Assert expect(errors[0]).toContain('fake reason'); }); section 2.5.1
AAA does not forbid reuse, but hiding Arrange and Act inside beforeEach() can create scroll fatigue and obscure each test’s actual setup. Keep phases visible when that improves understanding; use factory methods or limited reuse rather than placing unrelated state in shared setup. section 2.12 section 2.6.1
Listing 2.14 Pushing the arrange and act parts into beforeEach()
describe('PasswordVerifier', () => {
let verifier;
beforeEach(() => verifier = new PasswordVerifier1());
describe('with a failing rule', () => {
let fakeRule, errors;
beforeEach(() => {
fakeRule = input => ({passed: false, reason: 'fake reason'});
verifier.addRule(fakeRule);
errors = verifier.verify('any value');
});
it('has an error message based on the rule.reason', () => {
expect(errors[0]).toContain('fake reason');
});
it('has exactly one error', () => {
expect(errors.length).toBe(1);
});
});
});
Compare a compact shared setup with the resulting loss of local visibility when Arrange and Act move into beforeEach(). section 2.6.1





