intermediate15 min

Testing Legacy AngularJS Code

The classic Karma/Jasmine testing setup used by AngularJS-era applications.

What you'll learn

  • Recognize Jasmine's describe/it/expect testing structure in existing AngularJS test files
  • Explain what AngularJS's $httpBackend mock is used for in tests
  • Describe why an existing test suite is valuable context before modifying legacy behavior

Explanation

AngularJS-era applications were typically tested with Karma (a test runner that launches real browsers to execute tests) and Jasmine (the testing framework providing describe/it/expect). A typical test file structure: describe("MainController", () => { it("sets a default greeting", () => { /* ... */ expect(scope.greeting).toBe("Hello!"); }); }); -- describe groups related tests, each it is one test case, and expect(...).toBe(...) (or similar matchers) makes the actual assertion.

AngularJS's built-in testing utilities include $httpBackend, a mock for $http/$resource calls in tests -- it lets a test declare an expected request ($httpBackend.expectGET("/api/users").respond(200, [...])) without making a real network call, then verify the expected requests actually happened ($httpBackend.flush()/$httpBackend.verifyNoOutstandingRequest()).

Before modifying legacy AngularJS behavior, checking whether an existing test file already covers the code you're about to touch is genuinely valuable: passing tests give you a safety net for confirming your change didn't break existing behavior, and a test's describe/it names alone can clarify what a piece of legacy code was originally intended to do, which isn't always obvious from the implementation alone.

Guided lab

Predict: A Jasmine-style test's pass/fail result

AngularJSNot executed
This lab does not run in your browser or on VisaSparkSchools's servers. Read the code, predict what it does, then reveal the real expected output.

This models Jasmine's describe/it/expect structure with plain functions, since a real test runner can't execute here. Predict which test passes and which fails.

function greet(name) {
  return `Hello, ${name}!`;
}

function it(description, testFn) {
  try {
    testFn();
    console.log(`PASS: ${description}`);
  } catch (e) {
    console.log(`FAIL: ${description} -- ${e.message}`);
  }
}

function expect(actual) {
  return {
    toBe(expected) {
      if (actual !== expected) {
        throw new Error(`expected ${expected} but got ${actual}`);
      }
    },
  };
}

it("greets with the given name", () => {
  expect(greet("Ada")).toBe("Hello, Ada!");
});

it("greets with a different name (deliberately wrong expectation)", () => {
  expect(greet("Grace")).toBe("Hi, Grace!");
});

Stuck? Get a hint.

Common mistakes

  • Skipping a check for existing tests before modifying legacy behavior, missing a ready-made safety net for the change.
  • Confusing $httpBackend (a testing mock) with $http (the real service used in application code) -- they're related but serve different purposes.
  • Assuming Jasmine's describe/it structure is unique to AngularJS -- it's a general JavaScript testing framework, also used well beyond AngularJS specifically.

Knowledge check

Knowledge check

1. What does Jasmine's `describe` do?
2. What is $httpBackend used for?
3. Why is checking for existing tests valuable before modifying legacy code?

Takeaway

Check for existing Jasmine tests (and $httpBackend-mocked HTTP expectations) before modifying legacy behavior -- they're a safety net and a source of intent.

Summary

AngularJS-era apps typically use Karma+Jasmine (describe/it/expect) for tests, with $httpBackend mocking HTTP calls; existing tests are valuable context before making changes.

References

Your notes

Notes save automatically.