# Angularjs Unit Testing

> Use this skill for any AngularJS unit testing tasks

- Skill: `tomevault-io/angularjs-unit-testing` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/angularjs-unit-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/angularjs-unit-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/angularjs-unit-testing

---


# AngularJS Unit Testing Skill

## Overview

This skill specializes in writing, refactoring, and maintaining high-quality unit tests for AngularJS applications using both **Jasmine** and **Jest**. It provides comprehensive guidance on testing controllers, services, filters, directives, and other AngularJS components.

## Skill Capabilities

### Core Testing Competencies

- **Controllers**: Write tests for controller logic, state management, and event handling
- **Services**: Test factory/service dependencies, HTTP calls, and business logic
- **Filters**: Validate filter transformations and edge cases
- **Directives**: Test directive compilation, linking, and DOM manipulation
- **HTTP Mocking**: Mock HTTP calls using `$httpBackend` (Jasmine) or `jest.mock()` (Jest)
- **Promises & Async**: Handle `$q`, deferred objects, and `$timeout`
- **Dependency Injection**: Test with mocked and real dependencies
- **Scope Management**: Test scope lifecycle, watchers, and event broadcasting
- **Coverage Analysis**: Generate and interpret code coverage reports
- **Test Organization**: Structure tests following best practices and maintainability principles
- **Framework Choice**: Understand when to use Jasmine vs Jest, or both

### Testing Patterns

This skill implements the following testing patterns:

1. **AAA Pattern (Arrange-Act-Assert)**
   - Organize tests with clear setup, execution, and verification phases
   - Improves readability and maintainability

2. **Mocking & Spying**
   - Use Jasmine spies or Jest mocks to mock functions and verify calls
   - Mock HTTP responses and service dependencies
   - Simulate user interactions

3. **Test Fixtures**
   - Create reusable test data and helper functions
   - Use beforeEach/afterEach for common setup/teardown
   - Reduce test duplication

4. **Edge Case Testing**
   - Test boundary conditions, empty states, and error scenarios
   - Validate error handling and graceful degradation
   - Test asynchronous operations and race conditions

5. **Snapshot Testing** (Jest)
   - Capture expected component output
   - Detect unintended changes in UI rendering

## Testing Frameworks & Test Runners

### Jasmine (Recommended for AngularJS)

Jasmine is a behavior-driven development (BDD) testing framework optimized for unit testing AngularJS applications.

**Key Concepts**:
- `describe()`: Group related tests into a test suite
- `it()`: Define individual test cases
- `expect()`: Create assertions
- `beforeEach()` / `afterEach()`: Setup and teardown hooks
- `spyOn()` / `jasmine.createSpy()`: Mock functions and track calls

**Setup**:
```bash
npm install --save-dev jasmine karma karma-jasmine karma-chrome-launcher
```

### Jest (Modern Alternative)

Jest is a modern testing framework with powerful mocking, coverage, and snapshot testing capabilities. It can also test AngularJS applications with appropriate configuration.

**Key Concepts**:
- `describe()`: Group related tests (same as Jasmine)
- `test()` or `it()`: Define individual test cases
- `expect()`: Create assertions (Jasmine-compatible)
- `beforeEach()` / `afterEach()`: Setup and teardown hooks
- `jest.fn()`: Create mock functions
- `jest.mock()`: Mock modules

**Setup**:
```bash
npm install --save-dev jest jest-preset-angular @angular/core
```

**Jest Configuration** (package.json or jest.config.js):
```javascript
{
  "preset": "jest-preset-angular",
  "setupFilesAfterEnv": ["<rootDir>/setup-jest.ts"],
  "testPathIgnorePatterns": ["/node_modules/", "/dist/"],
  "collectCoverage": true,
  "collectCoverageFrom": ["src/**/*.js", "!src/**/*.spec.js"]
}
```

### Karma (Test Runner for Jasmine)

Karma is a test runner that executes Jasmine tests in real browsers and provides reporting.

**Configuration**:
- `karma.conf.js`: Main configuration file
- Specifies browser environment, files to load, and plugins
- Supports code coverage reporting and CI integration

## Test Structure

### Jasmine Test Structure (Recommended for AngularJS)

All Jasmine tests follow this standard structure:

```javascript
describe('Component Name', function() {
  var componentUnderTest, dependencies;

  // Load the module
  beforeEach(module('myApp'));

  // Inject dependencies
  beforeEach(inject(function($injector) {
    componentUnderTest = $injector.get('ComponentName');
    dependencies = $injector.get('DependencyName');
  }));

  // Cleanup after each test
  afterEach(function() {
    // Cleanup code
  });

  describe('Functionality Group', function() {
    it('should do something specific', function() {
      // Arrange
      var input = 'test';

      // Act
      var result = componentUnderTest.method(input);

      // Assert
      expect(result).toBe('expected');
    });
  });
});
```

### Jest Test Structure (Modern Alternative)

Jest tests follow a similar structure but with some differences:

```javascript
describe('Component Name', () => {
  let componentUnderTest;
  let dependencies;

  beforeEach(() => {
    // Setup code or mock initialization
    componentUnderTest = require('./component').default;
    dependencies = jest.mock('./dependency');
  });

  afterEach(() => {
    // Cleanup code
    jest.clearAllMocks();
  });

  describe('Functionality Group', () => {
    test('should do something specific', () => {
      // Arrange
      const input = 'test';

      // Act
      const result = componentUnderTest.method(input);

      // Assert
      expect(result).toBe('expected');
    });
  });
});
```

**Key Differences**:
- Jest uses arrow functions (ES6) while Jasmine supports both
- Jest uses `test()` or `it()` (both work)
- Jest uses `jest.mock()` instead of Jasmine spies for module mocking
- Jest auto-discovers `.spec.js` and `.test.js` files
- Jest provides built-in snapshot testing and code coverage

## Best Practices

### 1. Test Organization
- One test file per component (e.g., `controller.spec.js` for `controller.js`)
- Organize tests into logical groups using `describe()`
- Use meaningful test names that describe expected behavior

### 2. DRY Principle (Don't Repeat Yourself)
- Extract common setup into `beforeEach()` blocks
- Create reusable test data fixtures
- Use helper functions to reduce duplication

### 3. Test Independence
- Each test should be independent and runnable in any order
- Clean up resources in `afterEach()`
- Avoid shared state between tests

### 4. Realistic Mocks
- Mock external dependencies realistically
- Use actual data structures when possible
- Avoid overly simplified or unrealistic mocks

### 5. Comprehensive Coverage
- Aim for 80%+ code coverage
- Test happy paths, edge cases, and error scenarios
- Test async operations and race conditions

### 6. Performance
- Keep tests fast (< 100ms per test)
- Use in-memory mocks instead of real HTTP requests
- Avoid unnecessary database operations

### 7. Maintainability
- Write tests that are easy to understand
- Use the AAA pattern for clarity
- Document complex test logic with comments
- Refactor tests when the component changes

## Common Testing Scenarios

### Testing Controllers

```javascript
describe('UserController', function() {
  var $scope, controller;

  beforeEach(module('myApp'));
  beforeEach(inject(function($controller, $rootScope) {
    $scope = $rootScope.$new();
    controller = $controller('UserController', {
      $scope: $scope
    });
  }));

  it('should initialize with default values', function() {
    expect($scope.users).toBeDefined();
  });

  it('should load users on init', function() {
    expect($scope.users.length).toBeGreaterThan(0);
  });
});
```

### Testing Services

```javascript
describe('UserService', function() {
  var userService, $httpBackend;

  beforeEach(module('myApp'));
  beforeEach(inject(function(_UserService_, _$httpBackend_) {
    userService = _UserService_;
    $httpBackend = _$httpBackend_;
  }));

  afterEach(function() {
    $httpBackend.verifyNoOutstandingExpectation();
  });

  it('should fetch users from API', function() {
    var expectedUsers = [{ id: 1, name: 'John' }];
    $httpBackend.expectGET('/api/users').respond(expectedUsers);

    userService.getUsers().then(function(users) {
      expect(users).toEqual(expectedUsers);
    });

    $httpBackend.flush();
  });
});
```

### Testing with Promises

```javascript
describe('PromiseService', function() {
  var service, $q, $rootScope;

  beforeEach(inject(function(_Service_, _$q_, _$rootScope_) {
    service = _Service_;
    $q = _$q_;
    $rootScope = _$rootScope_;
  }));

  it('should handle promise resolution', function() {
    var deferred = $q.defer();
    var result;

    service.asyncOperation().then(function(data) {
      result = data;
    });

    deferred.resolve('success');
    $rootScope.$apply();

    expect(result).toBe('success');
  });
});
```

## Debugging Tests

### Jasmine Debugging

```javascript
// Skip a test
xit('should do something', function() { ... });

// Run only this test
fit('should do something', function() { ... });

// Console logging in tests
it('should debug', function() {
  console.log('Current state:', $scope);
  expect(true).toBe(true);
});
```

### Jest Debugging

```javascript
// Skip a test
test.skip('should do something', () => { ... });

// Run only this test
test.only('should do something', () => { ... });

// Debug with Node inspector
// Run: node --inspect-brk node_modules/.bin/jest --runInBand
```

## Integration with CI/CD

### GitHub Actions Example

```yaml
name: Test
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
      - run: npm install
      - run: npm test -- --coverage
      - uses: codecov/codecov-action@v2
```

### Jenkins Example

```groovy
pipeline {
  stages {
    stage('Test') {
      steps {
        sh 'npm install'
        sh 'npm test'
        publishHTML([
          reportDir: 'coverage',
          reportFiles: 'index.html',
          reportName: 'Coverage Report'
        ])
      }
    }
  }
}
```

## Resources

- [Jasmine Documentation](https://jasmine.github.io/)
- [Karma Test Runner](https://karma-runner.github.io/)
- [Jest Documentation](https://jestjs.io/)
- [jest-preset-angular](https://github.com/thymikee/jest-preset-angular)
- [AngularJS Testing Guide](https://docs.angularjs.org/guide/unit-testing)
- [Angular Testing Guide](https://angular.io/guide/testing)

## Troubleshooting

### Tests not running
- Check that module is loaded: `beforeEach(module('myApp'))`
- Verify dependencies are injected: `beforeEach(inject(...))`
- Check for syntax errors

### Async tests timing out
- Ensure promises are resolved: `$rootScope.$apply()` or `$httpBackend.flush()`
- Use `done()` callback: `it('...', function(done) { ... done(); })`
- For Jest: use `async/await` or return promise

### HTTP mocks not working
- Verify mock is set up before service call
- Check exact URL match in expectations
- Use `passThrough()` for unmocked requests

### Coverage gaps
- Review untested branches in coverage reports
- Test error conditions and edge cases
- Mock external dependencies properly

## Next Steps

1. **Start Small**: Write tests for a single component
2. **Understand Patterns**: Study the testing patterns guide
3. **Use Templates**: Reference template files for your component type
4. **Refine**: Improve tests based on coverage and feedback
5. **Automate**: Integrate tests into your CI/CD pipeline
6. **Share**: Document testing patterns for your team

---

**Specialization**: AngularJS Unit Testing with Jasmine and Jest  
**Version**: 1.0  
**Last Updated**: January 10, 2026

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/greedychipmunk) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-11 -->

