'What I am doing wrong when testing this method?

I am trying to test a method within a service that performs an http post. I have mock the service in my spec.ts and all seems correct for me, but the boolean variable that I expect true is showing false. This is the Jasmine spec list failure report:

Spec List | Failures
SkillAddService > Testing postSkillforMember() success
Expected false to be truthy.

This the method I want to test:

postSkillforMember(memberId: string, skillFormBody: any, successCallback: Function, errorCallback: Function) {
    this._http
      .post<Skill>(`${this._membersUrl}/${memberId}/skills`, skillFormBody, {
        headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
        responseType: 'json',
        observe: 'body',
      })
      .subscribe({
        next: (value) => { 
          this.newSkill = value;
        },
        complete: () => { 
          console.log("entrando");
          successCallback(this.newSkill);

        },
        error: (error) => { catchError(this.handleError);
          errorCallback(error);
        }
    });
  }

And this is my spec.ts file. I mock the service and then call the method with dummy but correct parameters:

describe('SkillAddService', () => {

  let mockHttp: HttpClient;
  let mockSkillAddService: jasmine.SpyObj<SkillAddService>;

  beforeEach(() => {
    mockSkillAddService = jasmine.createSpyObj<SkillAddService>('SkillAddService', ['postSkillforMember']);
    TestBed.configureTestingModule({
      imports: [
        HttpClientTestingModule
      ],
      providers: [{provide: SkillAddService, useValue: mockSkillAddService}]
    });
    mockHttp = TestBed.inject(HttpClient);
   
  });

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

  it('Testing postSkillforMember() success', () => {

    const skillFormBody = {
      skill: {
          "id": '1',
          "skill": ""
      },
      skillLevel: {
          "id": '1',
          "skillLevel": ""
      }
    }
    let successCallback = false;
   
    mockSkillAddService.postSkillforMember('1', skillFormBody, () => {successCallback = true}, () => {})
    expect(successCallback).toBeTruthy();
  });
});

Thank you in advance, I really appreciate your help!



Solution 1:[1]

mockSkillAddService.postSkillforMember is an asynchronous function. It return before it calls the callback function.

Therefore successCallback is still false when you reach the expect.

Try wrapping your call to mockSkillAddService.postSkillforMember in a promise.

it('Testing postSkillforMember() success', async () => {
    ...
    const successCallback = await new Promise(resolve => mockSkillAddService.postSkillforMember('sdfsdfds', skillFormBody, () => 
    resolve(true), () => resolve(false)))
    expect(successCallback).toBeTruthy();
    ...

Solution 2:[2]

As far as I understand, you want to test the postSkillforMember of the SkillAddService. But in your test, you are mocking this method. That means, the real code will not be executed, and with that of course the variable you expect to change will not change.

You have to provide the real service:

providers: [SkillAddService]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jkoch
Solution 2 slim