Search code examples
angularunit-testingkarma-jasminejasmin

Karma Error: Expected one matching request for criteria found 2 requests


Hi I am trying to write a unit test case for subscribe method of a controller.

I am getting the below error for the second test case

Error: Expected one matching request for criteria "Match URL: https://reqres.in/api/users?page=2", found 2 requests.
    at HttpClientTestingBackend.expectOne (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/common/fesm2015/http/testing.mjs:279:19)
    at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/src/app/admin/employee/employee.component.spec.ts:73:26)
    at _ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/fesm2015/zone.js:372:1)

Employee.controller.ts

import { Component,OnInit } from '@angular/core';
import { EmployeeService } from 'src/app/Service/employee.service';

@Component({
  selector: 'app-employee',
  templateUrl: './employee.component.html',
  styleUrls: ['./employee.component.css']
})
export class EmployeeComponent implements OnInit {
  public employeeDetails:any[] = [];
  public newEmployee:any = {
   name:"",
    job:""
  }

  constructor(public employee:EmployeeService) { }

  ngOnInit(): void {
    this.getEmployeeList();
  }
  

  getEmployeeList(){
    this.employee.getEmployeeList().subscribe(
      data=>{
        this.employeeDetails = data.data;
        console.log(data);
      },
      error=>{
        console.log(error);
      }
    )

  }

  AddNewEmployee(){
    this.employeeDetails.push(this.newEmployee);
  }
  
  DeleteEmployee(id:Number){
    this.employee.deleteEmp(id).subscribe(
      data=>{
        console.log(data);
      }
    )
  }
}

Employee.controller.spec.ts

import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

import { EmployeeComponent } from './employee.component';
import { EmployeeService } from 'src/app/Service/employee.service';

describe('EmployeeComponent', () => {
  let component: EmployeeComponent;
  let fixture: ComponentFixture<EmployeeComponent>;
  let service: EmployeeService;
  let httpMock: HttpTestingController;

  const emp = {
    data: [
      {
        "id": 7,
        "email": "[email protected]",
        "first_name": "Michael",
        "last_name": "Lawson",
        "avatar": "https://reqres.in/img/faces/7-image.jpg"
      },
      {
        "id": 8,
        "email": "[email protected]",
        "first_name": "Lindsay",
        "last_name": "Ferguson",
        "avatar": "https://reqres.in/img/faces/8-image.jpg"
      },
      {
        "id": 9,
        "email": "[email protected]",
        "first_name": "Tobias",
        "last_name": "Funke",
        "avatar": "https://reqres.in/img/faces/9-image.jpg"
      }
    ]
  }

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      declarations: [EmployeeComponent],
      providers: [EmployeeService]
    });
    fixture = TestBed.createComponent(EmployeeComponent);
    component = fixture.componentInstance;
    service = TestBed.inject(EmployeeService);
    httpMock = TestBed.inject(HttpTestingController);
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should call ngonInit method', () => {
    spyOn(component, 'ngOnInit').and.callThrough();
    component.ngOnInit();
    expect(component.ngOnInit).toHaveBeenCalled();
  });

  it('should return list of employees', () => {
    service.getEmployeeList().subscribe((data) => {
      expect(data).toEqual(emp.data);
    })

    const req = httpMock.expectOne('https://reqres.in/api/users?page=2');
    expect(req.request.method).toBe('GET');
    req.flush(emp.data);
    httpMock.verify();
  })

});

Can somebody help me by letting me know what mistake I am making here and what is the meaning of the error Error: Expected one matching request for criteria "Match URL: https://reqres.in/api/users?page=2", found 2 requests.


Solution

  • Can you show the ngOnInit? I bet the ngOnInit does getEmployeeList as well and you do service.getEmployeeList in the test also meaning there are two API calls where you are saying there is one (httpMock.expectOne(.

    To fix it, I would change the 2nd test to:

    it('should return list of employees', fakeAsync(() => {
        const req = httpMock.expectOne('https://reqres.in/api/users?page=2');
        expect(req.request.method).toBe('GET');
        req.flush(emp.data);
    
        // Add an expect on the component here (something like this).
        // Use fakeAsync/tick to ensure the subscribe of the ngOnInit
        // completed before our assertion.
        tick();
        expect(component.employees).toEqual(emp.data);
        
        httpMock.verify();
      }))