How to Mock a Backend in Angular using HttpInterceptor

Learn how to mock a backend using HttpIntercetor to make your testings simpler and easier.

Like the name implies HttpInterceptor is used to intercept HTTP calls (requests and responses) from our Angular app. There are many things we can do with HttpInterceptors:

Authentication

Caching

Fake backend

URL transformation

Modifying headers

and so on…

In this post, we will see how we to mock a backend using HttpInterceptors.

Faking a backend

There are times when we want to put up a fast server for testing out our Angular app behavior. We will find even making the simplest server from Nodejs or any other lang framework very tedious. We just want simple stuff that will just serve us JSON objects very fast.

The HttpInterceptor was introduced in Angular 4.0.3. Although, it is a very brilliant addition it has some behavior we have to take note of from Angular Docs:

Although interceptors are capable of mutating requests and responses, the HttpRequest and HttpResponse instance properties are read-only, rendering them largely immutable.

To modify a HttpRequest we use the clone method.

Angular applies interceptors in the order that you provide them. If you provide interceptors A, then B, then C, requests will flow in A -> B -> C and responses will flow out C -> B -> A. You cannot change the order or remove interceptors later. If you need to enable and disable an interceptor dynamically, you’ll have to build that capability into the interceptor itself.

First, we create a BackendInterceptor class:

@Injectable()

class BackendInterceptor implements HttpInterceptor {

...

}

See, it starts with implementing the HttpInterceptor interface. This is Angular obeying the DIP (Dependency Inversion Principle). The request method in HttpClient is called whenever we make a HTTP(GET, POST, DELETE, OPTIONS) call, the call passes through the HttpHandler, this class is passed a param which should be of HttpInterceptor instance because HttpHandler will call the intercept method on it. So Angular makes sure we implement the HttpInterceptor interface so we pass any type of HttpInterceptor we want, without breaking the Http module. Cool!!!

So we will add the intercept method on our BackendHttpInterceptor class:

@Injectable()

class BackendInterceptor implements HttpInterceptor {

constructor(private injector: Injector) {} intercept(request: HttpRequest, next: HttpHandler): Observable<HttpEvent<any>> {

...

}

}

We will insert our implementation between the intercept braces. Whatever we do there, we must pass the HttpRequest to the chain by returning an Observable with the Http request passed into it.

Here, we will intercept the Http call and return an Observable of HttpResponse. This will stop the Http request from reaching the final chain to the XmlHttpRequest#send method.

Tip: Another great tool for Angular developers is Bit (Github). Bit lets you easily share and collaborate on Angular components. Collaborate on shared components to keep a consistent and bulletproof UI, and build faster as a team.

Example: Shared reusable components in bit.dev

Creating our fake server data

Now, we want an array of users from our server. So we will create a fake server data.

... const usersData = {

"users": [

{

"name": "chidume nnamdi",

"age": 26

},

{

"name": "chisom",

"age": 46

},

{

"name": "elvis",

"age": 21

},

{

"name": "osy mattew",

"age": 21

},

{

"name": "valentine",

"age": 21

},

]

} @Injectable()

class BackendInterceptor implements HttpInterceptor {

constructor(private injector: Injector) {} intercept(request: HttpRequest, next: HttpHandler): Observable<HttpEvent<any>> {

...

}

}

The user property in the usersData contains a list of our user’s name and age we want for our Angular app.

We can put it in a separate JSON file or inside the class like we just did.

Now, let’s return the usersData in our BackendHttpInterceptor class.

Returning the data

... const usersData = {

"users": [

{

"name": "chidume nnamdi",

"age": 26

},

{

"name": "chisom",

"age": 46

},

{

"name": "elvis",

"age": 21

},

{

"name": "osy mattew",

"age": 21

},

{

"name": "valentine",

"age": 21

},

]

} @Injectable()

class BackendInterceptor implements HttpInterceptor {

constructor(private injector: Injector) {} intercept(request: HttpRequest, next: HttpHandler): Observable<HttpEvent<any>> {

return of(new HttpResponse({ status: 200, body: usersData }));

}

}

We created a HttpResponse with a status of 200 (which means OK to the browser) and the body payload set to our usersData. We passed the instance to the Observable#of(...) call and returns the Observable.

We just simply returned the usersData. With this, all Http requests will return the usersData. We would modify to match a URL when an API is requested with a GET method. Like from localhost:4200/users/ .

So our BackendHttpInceptor will be this:

...

@Injectable()

class BackendInterceptor implements HttpInterceptor {

constructor(private injector: Injector) {} intercept(request: HttpRequest, next: HttpHandler): Observable<HttpEvent<any>> {

if(request.method === "GET" && request.url === "http://localhost:4200/users") {

return of(new HttpResponse({ status: 200, body: usersData }));

}

next.handle(request)

}

}

What did we do? We used the request param an instance of HttpRequest, this HttpRequest represents an outgoing HTTP request including URL, method, headers, body, and other request configuration options. We check if the method of the request is a GET method and the url is equal to http://localhost:4200/users , the API we use to get the usersData data. If equal we know we are requesting for the user's data so we serve the usersData as response and cut the chain, if not we pass the request on to the next line in the chain using the next.request() call, the next param an instance of HttpHandler this call will dispatch the request to another interceptor in the chain till it eventually reaches the HttpBackend , the final HttpHandler which dispatch the request to the browser HTTP APIs to a backend.

So our BackendHttpInterceptor will give feed us fake data when we call the http://localhost:4200/users in our component or service

@Component({

...

})

export class AppComponent {

users: Array<User> constructor(private httpClient: HttpClient) {} ngOnInit() {

this.httpClient.get("http://localhost:4200:/users").subscribe( res => this.users = res.users)

}

}

... @Injectable()

export class UserService {

getUsers(): Observable {

return this.httpClient.get("http://localhost:4200:/users")

}

}

without reaching an actual server backend.

Regsitering our BackendHttpInterceptor

We will add the BackendHttpInterceptor in our main module, here in our project it would be AppModule:

@NgModule({

...

providers: [

{

provide: HTTP_INTERCEPTORS,

useClass: BackendHttpInterceptor,

multi: true

}

]

...

})

export class AppModule {}

See, to register our interceptor we create an object with the provide property set to the HTTP_INTERCEPTORS token exported by the CommonModule and a useClass property set to our BackendHttpInterceptor. The object is added to the providers array in the NgModule decorator.

We are done. So simple, we just serve our app ng serve and test it out.

Conclusion

Interceptors are great!! It is left for us to think of something excellent to implement with it.

In the next posts, we will be looking at the use cases for HttpInterceptor we listed in the beginning. Stay tuned.

If you have any questions regarding this or anything I should add, correct or remove, feel free to comment, email or DM me.

Thanks !!!

Learn More