Search code examples
jsonangularjasminekarma-jasminekarma-runner

How to write a karma-Jasmine test for a dynamic configuration file JSON


I am very new to writing tests in Karma and Jasmine. In my case, I have a dynamic configuration file that loads before the app is initialized and that file is a JSON with a value.

configuration.json

{
    "sampleConfigValue": "this is a sample value from config"
}

Configuration.ts

export interface Configuration {
    sampleConfigValue: string;
}

ConfigurationService.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Configuration } from './configuration';
@Injectable({
  providedIn: 'root'
})
export class ConfigurationService {
  private configData: any | undefined;
  private readonly configPath: string = '../assets/demo/data/config.json';
  constructor(
    private http: HttpClient
  ) { }

  async loadConfiguration(): Promise<any> {
    try {
      const response = await this.http.get(`${this.configPath}`)
        .toPromise().then(res => this.configData = res);     
      return this.configData;
    } catch (err) {
      return Promise.reject(err);
    }
  }

  get config(): Configuration | undefined {
    return this.configData;
  }
}

Exporting the ConfigurationLoader in app.module.ts

export function configLoader(injector: Injector) : () => Promise<any>
{
    return () => injector.get(ConfigurationService).loadConfiguration(); 
}

and Provider in app.module.ts

{provide: APP_INITIALIZER, useFactory: configLoader, deps: [Injector], multi: true},

configuration.service.spec.ts

import { TestBed } from '@angular/core/testing';

import { ConfigurationService } from './configuration.service';

describe('ConfigurationService', () => {
  let service: ConfigurationService;

  beforeEach(() => {
    TestBed.configureTestingModule({});
    service = TestBed.inject(ConfigurationService);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });
});

The configuration file is working but I am wondering how to write a test case for this dynamic configuration in my project?

Your time and help will really help me :)

Thanks :)


Solution

  • When unit testing, you're supposed to test a code unit and mock the rest.

    So create a mock then test :

    
    // Put this in the main describe
    const returnValue = {};
    let httpMock: { get: jasmine.Spy };
    let service: ConfigurationService;
    
    // Put this in the main beforeEach
    httpMock = {
      get: jasmine.createSpy().and.returnValue(of(returnValue)),
    };
    service = new ConfigurationService(<any>httpMock);
    
    // Make a meaningful test
    it('Should call the endpoint and retrieve the config', (done) => {
      service.loadConfiguration().then(() => {
        expect(httpMock.get)
          .toHaveBeenCalledOnceWith(service['configPath']);
        expect(service['configData']).toBe(returnValue);
        done();
      });
    });