Labs ICT
Pro Login

Testing Error Handling

Making sure your error paths work.

Testing Error Handling

Your code will face bad input, network failures, and unexpected states. Testing error handling means you know your app will handle these gracefully instead of crashing.

One thing that confused me at first was how much error testing to do. The answer is: test every error path you care about. If your function can fail in three ways, write three tests for it.

Testing Try/Catch Blocks

When your code catches errors, test that it handles them correctly.


function parseJSON(str) {
  try {
    return JSON.parse(str);
  } catch (e) {
    return null;
  }
}

describe('parseJSON', () => {
  it('parses valid JSON', () => {
    expect(parseJSON('{"name":"Alice"}')).toEqual({ name: 'Alice' });
  });

  it('returns null for invalid JSON', () => {
    expect(parseJSON('not json')).toBeNull();
  });

  it('returns null for empty string', () => {
    expect(parseJSON('')).toBeNull();
  });
});
    

Testing Error Messages

When your code throws, verify the error message is correct. This helps with debugging when something goes wrong.


function setAge(age) {
  if (typeof age !== 'number') {
    throw new TypeError('Age must be a number');
  }
  if (age < 0 || age > 150) {
    throw new RangeError('Age must be between 0 and 150');
  }
  return age;
}

it('throws TypeError for non-number', () => {
  expect(() => setAge('old')).toThrow(TypeError);
  expect(() => setAge('old')).toThrow('Age must be a number');
});

it('throws RangeError for invalid age', () => {
  expect(() => setAge(-5)).toThrow(RangeError);
  expect(() => setAge(-5)).toThrow('Age must be between 0 and 150');
});
    

Testing Edge Cases

Edge cases are where bugs love to hide. Test boundaries, empty values, null, undefined, and zero.


function getFirst(arr) {
  if (!Array.isArray(arr)) throw new TypeError('Input must be array');
  if (arr.length === 0) return undefined;
  return arr[0];
}

it('returns first element', () => {
  expect(getFirst([1, 2, 3])).toBe(1);
});

it('returns undefined for empty array', () => {
  expect(getFirst([])).toBeUndefined();
});

it('throws for non-array input', () => {
  expect(() => getFirst('hello')).toThrow(TypeError);
});
    
Try it Yourself →

Key Takeaways

  • Test every error path your function can take
  • Verify both the error type and the error message
  • Test edge cases like null, undefined, empty arrays, and zero
  • Use toThrow to check both error class and message
  • Error handling tests prevent crashes in production