In production-grade Angular applications, API URLs and other environment-specific properties are typically configured through environment files located in the src/environments/ directory. These can be generated using the Angular CLI command:

ng generate environments

This creates the standard environment files:

  • environment.ts (production defaults)
  • environment.development.ts (development configuration)
  • You could add other environments like staging...

Secure Configuration Management

For security best practices:

  • Never commit sensitive URLs directly in environment files
  • Use CI/CD variables (GitLab, GitHub Actions, etc.) to inject values during build

Protect repository variables by marking them as:

  • Masked (hidden in logs)
  • Protected (only available on protected branches)

Update the files:
environment.ts

export const environment = {
    production: true,
    API_URL: '${API_URL}' // CI/CD variable - This will be replaced during build
};

environment.development.ts

export const environment = {
  production: false,
  API_URL: 'https://api.example.com/data' // Used only in development
};

Use the environment variables:
data-http.service.ts

...
import { environment } from '../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class DataHttpService {
  http = inject(HttpClient);

  getData(): Observable<unknown> {
    return this.http.get<unknown>(environment.API_URL);
  }
}

Unit testing with environment mocks

You could add an environment global mock in setup-jest.ts:

...

jest.mock('./src/environments/environment', () => ({
  environment: {
    API_URL: 'https://api.example.com/data',
    production: false
  }
}));

Mocking environment variables in unit tests is strongly recommended to ensure isolation, consistency, and security while testing all scenarios.

data-http.service.spec.ts

import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { DataHttpService } from './data-http.service';
import { environment } from '../environments/environment';


describe('DataHttpService', () => {
  let service: DataHttpService;
  let httpMock: HttpTestingController;
  const mockData = { id: 1, name: 'Test Data' };

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [DataHttpService]
    });

    service = TestBed.inject(DataHttpService);
    httpMock = TestBed.inject(HttpTestingController);
  });

  afterEach(() => {
    httpMock.verify();  // Verify no outstanding requests
  });

  it('should use mock API_URL', () => {
    expect(environment.API_URL).toBe('https://api.example.com/data'); // Url defined in the setup-jest.ts file
  });

  describe('.getData', () => {
        it('should make GET request and return data', () => {
        service.getData().subscribe(data => {
          expect(data).toEqual(mockData);
        });

        const req = httpMock.expectOne(environment.API_URL);
        expect(req.request.method).toEqual('GET');
        req.flush(mockData);
      });
    });
});