Pawan Kumar
Pawan Kumar

Reputation: 522

Angular Mock Service is not getting Called in Component Spec (Karma)

Trying to write test cases for mainchat.component.ts but i am not able to figure it out.(New to Karma). Sample Code below

 getActiveUsers(): void {    
    this._ChatService.getActiveUserInfo().subscribe(data => {
      this.Users = data;          
    }, err => {
      console.log(err);
    });
  }

And the ChatService is as below:

@Injectable()
export class ChatService {
  constructor(private _http: HttpClient) { }
  getActiveUserInfo(): any {        
    return this._http
        .get<any>(Globaldata.API_ENDPOINT_LOCAL + '/api/getActiveUsers')
        .do(data => console.log('All this : ' + JSON.stringify(data)))
}
getActiveGroupInfo(): any {      
  return this._http
      .get<any>(Globaldata.API_ENDPOINT_LOCAL + '/api/getActiveGroups')
      .do(data => console.log('All this : ' + JSON.stringify(data)))
  }
}

I am trying to write the test cases for the above Component but not able to figure out how to stub the services

  class MockChatService extends ChatService {    
  constructor() {
      super(null);
  }    
  testActiveUser: Array < USER > = [
      new USER(),
      new USER()
  ];    
  testActiveGroup: Array < GROUP > = [
      new GROUP()
  ];    

  public getActiveUserInfo(): Observable < USER[] > {
    return Observable.of(this.testActiveUser);
  }

  public getActiveGroupInfo(): Observable < GROUP[] > {
    return Observable.of(this.testActiveGroup);
  }
}

describe('InstantMessangerComponent (inline template)', () => {

  let chatService: MockChatService;
  let component: InstantMessangerComponent;
  let fixture: ComponentFixture < InstantMessangerComponent > ;

  beforeEach(async (() => {
      TestBed.configureTestingModule({
              imports: [FormsModule, HttpClientModule, HttpModule],
              declarations: [InstantMessangerComponent, MessagewindowComponent, SearchuserPipe],
              providers: [{
                  provide: ChatService,
                  useClass: MockChatService
              }]
          }).overrideComponent(ChatService, {
              set: {
                  providers: [{
                      provide: ChatService,
                      useClass: MockChatService
                  }]
              }
          }).compileComponents() // compile template and css
          .then(() => {
              fixture = TestBed.createComponent(InstantMessangerComponent);
              component = fixture.componentInstance; // InstantMessangerComponent test instance
              chatService = TestBed.get(ChatService);
          });
  }));

  it('expects getActiveUsers() to have been called', function() {

      spyOn(component, 'getActiveUsers').and.callThrough();

      component.getActiveUsers();

      expect(component.getActiveUsers).toHaveBeenCalled();
  });
 });

The Test Suite is calling the Main ChatService rather than MockChatService.

Upvotes: 1

Views: 1623

Answers (1)

Huske
Huske

Reputation: 9296

what you need is to call spyOn. As far I as understand from the code provided getActiveUsers is in the mainchat.component.ts.

What you should do is something like following:

it('expects getActiveUsers() to have been called', function () {
    spyOn(component, 'getActiveUsers');

    expect(component.getActiveUsers).toHaveBeenCalled();
});

This should check that the method was called.

UPDATE

Another way is to get the reference to the injected service like:

const chatService = fixture.debugElement.injector.get(ChatService);
const spy = spyOn(chatService, 'getActiveUserInfo').and.returnsWithValue(Promise.resolve('whatever you want to return'));

expect(spy.calls.any).toBe(true);

The third option that you have is to provide a completely new service, like a fake service in your initialization (async version of beforeEach) and have it return some dummy data. But that would be nearly identical to the updated answer that gets a reference to the injected service and spies on it.

Upvotes: 1

Related Questions