Every developer understands how frustrating it is to call an API and have it fail or return an error. Apart from the frustration, this adds cost to the project.

Postman makes it simple for front-end developers to reduce or eliminate their dependency on the backend and servers. It is called Postman Mock Servers. In your Angular project, you just need to do some simple configuration to do the API call to the mock servers instead of the actual API.

In a nutshell, your front end will make the API call, the interceptor in the Angular project will intercept it, and based on the environment file in use, the call will either go to the mock server or to the actual API.

API

The flow of HTTP calls when using mock servers and interceptors

How can it help us?

Imagine you are a front-end developer working on a feature that requires you to call an API, and its response will provide you with the data to use and display. Every time you call the API, the server is down, or there are some issues with the backend that prevent you from making a successful call. Such a situation will slow you down and can block you.

Using the mock server will eliminate the dependency on the backend during development. Instead of calling the backend, your frontend will call the mock server and URL, which will return the mock response.

It is important to ask for the mock response/JSON from your backend team. Do not try to build one yourself, as you might not know exactly what will be returned. The backend team will have the documents and/or contract about the structure of the response, hence providing an accurate mock to you. Otherwise, you will end up developing based on a wrong response structure. When the actual API is called, and you will get the actual response, your feature might break.

Setting up the Postman mock server

Setting an Angular project to use the mock server

Create environment files in your angular project. More about this here: https://www.c-sharpcorner.com/article/harnessing-the-power-of-environments-using-angular/

For each environment, create an object for its corresponding base URL. Below is an example.

Angular project

Create an Interceptor: Interceptors are a powerful feature in Angular that helps manage HTTP communication in a clean and maintainable way.

An HttpInterceptor in Angular is a service that implements the HttpInterceptor interface and is used to intercept and handle HTTP requests and responses globally (across the whole project). Interceptors are part of Angular's HttpClient module and provide a way to modify or manipulate HTTP requests before they are sent to the server and responses before they are processed by the application.

Generate an interceptor service using the following.

ng generate service interceptors/mock-server

You will find your newly created service under app > interceptor

Below is the code for the interceptor. Note that I have called my mock-server. service.t.

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class MockServerInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const mockReq = req.clone({
      url: `${environment.baseUrl}${req.url}`
    });
    return next.handle(mockReq);
  }
}

The baseUrl is retrieved from the environment file. The ‘${req.url}’ is dynamic and will be the part after the ‘/’ in the API URL. The rest is boilerplate code.

In the app.module.ts, add the ‘HttpClientModule’ in the imports and the following line in the provider.

[
  { 
    provide: HTTP_INTERCEPTORS, 
    useClass: MockServerInterceptor, 
    multi: true 
  }
]

Once the two previous steps are done, the interceptor part is ready to be used.

You can now implement your API call.

For the sake of this example, I will call a function from the ngOnInit. This function will make the API call. Below is the code

constructor(private http: HttpClient) {}
ngOnInit(): void {
  console.log('loaded');
  this.makeApiCall();
}
makeApiCall(): void {
  this.http.get('/dinosaurs').subscribe({
    next: response => {
      console.log('API response:', response);
    },
    error: error => {
      console.error('API error:', error);
    }
  });
}

First, in the constructor, set the http client. If this is not done, you will get an error every time you use ‘this. HTTP.

The ‘/dinosaurs’ can be considered as the ‘${req. url}’ part from the interceptor.

Since we are using an environment file, the ‘baseUrl’ variable from the different environment files will be used based on the command used to serve the application. More information in this article: https://www.c-sharpcorner.com/article/harnessing-the-power-of-environments-using-angular/

In our example, if we build using ng serve, the environment.development.ts will be used, and hence the mock server will also be used.

Environment

When you check the response, you will see the mock response being returned.

Response

When you are using the ‘ng serve --configuration=production’ command, the environment.ts file will be used. Remember that no change in code is done. You just serve the application with the command required per environment. In this case, the actual API will be called.

Command

The response also will be the one from the actual API call.

API call

Why is the interceptor recommended?

Using an interceptor is recommended over directly calling the environment variable before each HTTP call for several reasons.

1. Centralized Logic

  1. Interceptor: An interceptor allows you to centralize and manage common logic for all HTTP requests in one place. This includes adding headers, handling authentication, logging, error handling, and modifying request URLs.
  2. Direct Call: If you use the environment variable directly in each call, you would need to repeat the same logic in multiple places, leading to code duplication and increased maintenance effort.

2. Separation of Concerns

  1. Interceptor: Keeps your components and services clean and focused on their primary responsibilities. The interceptor handles cross-cutting concerns like modifying URLs or adding headers.
  2. Direct Call: Mixing environment-specific logic with business logic can make your code harder to read and maintain.

3. Ease of Configuration

  1. Interceptor: You can easily switch between different environments (e.g., development, staging, production) by configuring the interceptor without changing the code in multiple places.
  2. Direct Call: You would need to update the environment variable in every HTTP call, which is error-prone and cumbersome.

4. Consistency

  1. Interceptor: Ensures that all HTTP requests are consistently handled in the same way, reducing the risk of missing configurations or headers in some requests.
  2. Direct Call: Increases the risk of inconsistencies if you forget to include the environment variable or headers in some requests.

Conclusion

Dependencies are a major blocker in the development world. Waiting for an issue to be resolved or for an API to work can be time-consuming. However, the front end and back end can easily be decoupled, eliminating the dependencies. In this way, front-end developers are able to work independently and without back-end constraints.

Postman makes it simple to set up mock servers, and Angular Interceptor helps us route API calls correctly.

In this article, we have seen how to do both and what the outcome is.

Resources