0

I am new to Jasmine, Karma testing. I was facing issue in writing the one of the test cases for service named AuthRealService which injected using an interface name AuthService into component LoginComponent.

here is AuthService interface

import { Observable } from 'rxjs';

export const AUTH_SERVICE = 'AUTH_SERVICE';
export interface AuthService {
  doAuthenticate(loginUser: any): Observable<any>;
}

here is my Real Service

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { SERVICE_URL } from 'src/app/shared/constants/service.constants';
import { ApiService } from 'src/app/shared/services/api.service';

import { AuthService } from './auth.service';

@Injectable()
export class AuthRealService implements AuthService {
  constructor(private apiService: ApiService) {}

  doAuthenticate(loginUser: any): Observable<any> {
    return this.apiService.post(SERVICE_URL.GET_DIRECT_LOGIN_URL, loginUser);
  }
}

Here is Mock Service

import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { Observable } from 'rxjs';
import { delay } from 'rxjs/operators';

import { AuthService } from './auth.service';

@Injectable()
export class AuthMockService implements AuthService {
  doAuthenticate(): Observable<any> {
    const MockSuccessResponse = {
      status: 'SUCCESS',
      data: [
        {
          status: 'Good'
        }
      ]
    };
    return of(MockSuccessResponse).pipe(delay(100));
  }
}

The LoginComponent is here

import { Component, Inject, OnInit, ViewContainerRef } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { NgxSpinnerService } from 'ngx-spinner';
import { APP_CONST } from 'src/app/shared/constants/app.constants';
import {
  COMMON_API_SERVICE,
  CommonApiService
} from 'src/app/shared/services/common-api.service';
import { CommonService } from 'src/app/shared/services/common.service';

import { VoyaPayCloudGlobalState } from 'src/app/shared/store/our-global.store';

import { ToastrService } from '../../../shared/services/toastr.service';
import { AUTH_SERVICE, AuthService } from '../../login/services/auth.service';

const noop = () => {};

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
  loginForm: FormGroup;
  isLabelHidden: boolean;
  errorCount = 0;
   _onTouchedCallback: (_: any) => void = noop;
   _onChangeCallback: (_: any) => void = noop;
  public loginFail;
  constructor(
    @Inject(AUTH_SERVICE) private authService: AuthService,
    @Inject(COMMON_API_SERVICE) private commonApiService: CommonApiService,
    private commonService: CommonService,
    private router: Router,
    private toastrService: ToastrService,
    private spinner: NgxSpinnerService,
    vcr: ViewContainerRef
  ) {
    this.toastrService.toastr.setRootViewContainerRef(vcr);
  }

  ngOnInit() {
    //Form intialization is done here
  }

  onSubmit() {
    //implmented after submit functionality here
  }

  login(): void {
  //implemented login functionality here
}

here is testing spec file

  HttpClient,
  HttpClientModule,
  HttpHeaders,
  HttpParams
} from '@angular/common/http';
import { DebugElement, ViewContainerRef } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BrowserModule, By } from '@angular/platform-browser';
import { Router, RouterModule } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { NgxSpinnerService } from 'ngx-spinner';
import { AppComponent } from 'src/app/app.component';
import { TextboxComponent } from 'src/app/shared/components/form/voya-textbox/voya-textbox.component';
import { SpinnerComponent } from 'src/app/shared/components/layout/spinner/spinner.component';
import { OurRoutingModule } from 'src/app/shared/modules/our-routing.module';
import { ApiService } from 'src/app/shared/services/api.service';
import { CommonApiRealService } from 'src/app/shared/services/common-api-real.service';
import { COMMON_API_SERVICE } from 'src/app/shared/services/common-api.service';
import { CommonService } from 'src/app/shared/services/common.service';
import { ToastrService } from 'src/app/shared/services/toastr.service';
import { AuthRealService } from '../services/auth-real.service';
import { AUTH_SERVICE } from '../services/auth.service';
import { LoginComponent } from './login.component';

fdescribe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let submitElement: DebugElement;
  let userNameElement: DebugElement;
  let passwordElement: DebugElement;
  let authRealServiceSpy: jasmine.SpyObj<AuthRealService>;
  beforeEach(() => {
    const authRealServiceSpyObj = jasmine.createSpyObj('AuthRealService', [
      'doAuthenticate'
    ]);
    TestBed.configureTestingModule({
    
      declarations: [LoginComponent, SpinnerComponent, TextboxComponent],
      imports: [
        BrowserModule,
        HttpClientModule,
        RouterTestingModule,
        OurRoutingModule
      ],
      providers: [
        { provide: AuthRealService, useValue: authRealServiceSpyObj },
        ApiService,
        HttpClient,
        { provide: COMMON_API_SERVICE, useClass: CommonApiRealService },
        CommonService,
        Router,
        ToastrService,
        NgxSpinnerService,
        ViewContainerRef
      ]
    });

    //create component test fixture
    fixture = TestBed.createComponent(LoginComponent);

    authRealServiceSpy = TestBed.inject(AuthRealService);

    //get the test component from the fixture
    component = fixture.componentInstance;
  });


});

In the Above spec file i was trying to authRealServiceSpy = TestBed.inject(AuthRealService); its saying "Type 'AuthRealService' is not assignable to type 'SpyObj'."

I was referring to this solution How to handle dependency injection into Angular unit test using Jasmine?

Can anyone please help me out to resolve this issue, early replies appreciated. Thanks in advance.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

0

Since authRealServiceSpy is of type SpyObj when you define it, create a new variable authRealService of type AuthRealService and then you can do authRealService = TestBed.inject(AuthRealService);

...
let passwordElement: DebugElement;
let authRealServiceSpy: jasmine.SpyObj<AuthRealService>;
let authRealService: AuthRealService;
.....
authRealService = TestBed.inject(AuthRealService);
AliF50
  • 16,947
  • 1
  • 21
  • 37