Introduction

This tutorial will walk you through the process of creating a basic unit test case for an Angular service. Angular services enable you to decompose complex business logic into small, reusable units that can then be injected into components or other services using dependency injection.

This tutorial is divided into two parts:

  • One for creating a service by instantiating it sing new keyword.
  • And another for injecting it using the Angular TestBed module.

Service

The structure of the Token class is shown in the following snippet. 

token.ts

export class Token {
  timestamp: number = 0;
  userId: number = 0;
}

The Token class contains the token’s expiration timestamp, user id, and token signature.

The next step is to validate this token object using an Angular service.

toke.service.ts

import { Token } from './token';

export class TokenService {

  isValidToken(token: Token): boolean {
    let currentTime = Date.now();
    let timeDifference: number = token.timestamp - currentTime;
    
    if (timeDifference < 0) {
      return false;
    } else {
      return true;
    }
  }
}

To validate the token, the service will compute the difference between the current time and the moment it was created. If the current time exceeds the token time or expiry time, the token is considered invalid, and the method returns the appropriate boolean value.

Now we can test the above method’s behaviour against two scenarios:

  • One with an expired token, which should return a false value
  • And one with a non-expired token, which should return a true value.

Unit Test

token.service.spec.ts

import { Token } from './token';
import { TokenService } from './token.service';

describe('TokenSerrvice test cases', () => {
  var tokenService: TokenService;
  var tokenTime: number;

  beforeEach(() => {
    tokenService = new TokenService();
  });

  it('Should return false for expired token', () => {
    tokenTime = Date.now() - 50;
    let token: Token = { timestamp: tokenTime, userId: 1212 };
    let result: boolean = tokenService.isValidToken(token);
    expect(result).toBeFalse();
  });

  it('Should return true for valid token', () => {
    tokenTime = Date.now() + 5000;
    let token: Token = { timestamp: tokenTime, userId: 1212 };
    let result: boolean = tokenService.isValidToken(token);
    expect(result).toBeTrue();
  });
});

beforeEach will create a new TokenService instance. Another way to obtain an instance of the service is to use the TestBed module, as seen below

TestBed Configuration

beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [TokenService]
    })
    tokenService = TestBed.inject(TokenService);
})

TestBed is an Angular-specific utility for unit testing; it allows us to auto-load services and any dependencies associated with them, and it provides a production-ready environment for unit testing.

Now the question is, which of these should I choose? The answer is dependent on your working style, if you want to control service creation, the first option is preferable, if you prefer Angular to handle service instantiation, the second option is advisable.

Conclusion

Angular services are lightweight and independent of UI components. Therefore, you can build the service and verify its behaviour using unit test cases without the need to bootstrap your Angular application and browser.

You can find source code on the Github page.