mccarthyj
mccarthyj

Reputation: 949

How to mock a response from an Angular service in a unit test

I have an Angular service that calls an api backend and returns a list of employees, in a project. I'm writing a unit test for the component that calls the service method, and mocking the service, but the mocked responses are not being assigned in the component, so the unit test is failing every time

./employee.ts

export interface Employee {
  id: string;
  name: string;
  dateOfBirth: string;
  dateJoined: string;
}

./employee.service.ts

@Injectable({
  providedIn: 'root',
})
export class EmployeeService {
  constructor(private http: HttpClient) { }

  getEmployees(countryId: string, branchId: string): Observable<Employee[]> {
    return this.http.get<Employee[]>(`api/employees/${countryId}/${branchId}`);
  }
}

./app.component.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  providers: [ EmployeeService ],
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {
  employees$!: Observable<Employee[]>;
  countryId: string = '';
  branchId: string = '';

  constructor(private employeeService: EmployeeService) {}

  search(): void {
    this.employees$ = this.employeeService.getEmployees(this.countryId, this.branchId);
  }
}

./app.component.spec.js

describe('Unit tests for AppComponent', () => {
  const mockEmployee = {
    id: "1234",
    name: "Mock Employee Name",
    dateOfBirth: "2000-01-01",
    dateJoined: "2020-01-01"
  };

  const mockEmployees = [mockEmployee];

  let fixture: ComponentFixture<AppComponent>;
  let app: AppComponent;
  let mockEmployeeService: jasmine.SpyObj<EmployeeService>;

  beforeEach(async () => {
    mockEmployeeService = jasmine.createSpyObj('EmployeeService', ['getEmployees']);
    await TestBed.configureTestingModule({
      declarations: [ AppComponent ],
      imports: [ HttpClientTestingModule, FormsModule ],
      providers: [ {provide: EmployeeService, useValue: mockEmployeeService} ]
    }).compileComponents();
    fixture = TestBed.createComponent(AppComponent);
    app = fixture.componentInstance;
  });

  it('should test the employees are returned correctly from the service', fakeAsync() => {
    const getEmployeesSpy = mockEmployeeService.getEmployees.and.returnValue(of(mockEmployees));

    // Search for all employees in region 1234 with no trade reference set
    app.countryId = "1234";
    app.branchId = "4321";
    app.search();
    fixture.detectChanges();

    expect(getEmployeesSpy.calls.any()).toBe(true);
    expect(app.employees$).toEqual(mockEmployees);
  });
});

What am I missing?

Upvotes: 0

Views: 6492

Answers (1)

wlf
wlf

Reputation: 3413

  • use waitForAsync instead of fakeAsync
  • replace your expects with:
expect(getEmployeesSpy).toHaveBeenCalled();
expect(app.employees$).toBeObservable(mockEmployees);

Upvotes: 1

Related Questions