0

I wrote service that request JSON via http:

export class TodosService {
  constructor(private http: HttpClient) {}
  getTodos(): Observable<any> {
    return this.http.get<any>('https://jsonplaceholder.typicode.com/todos');
  }
}

The component is assigned a value from the service:

export class TodosComponent implements OnInit {
  todos: any;
 
  constructor(private todosService: TodosService) {}
 
  ngOnInit() {
    this.todosService.getTodos().subscribe((todos) => {
      this.todos = todos;
    });
  }
}

I would like to test it. There is the unit-test:

describe('Page1Component', () => {
  let component: Page1Component;
  let fixture: ComponentFixture<Page1Component>;
  let spy: any;
  let todosService: TodosService;
 
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [Page1Component],
      imports: [HttpClientModule],
      providers: [TodosService],
    }).compileComponents();
  });
 
  beforeEach(() => {
    fixture = TestBed.createComponent(Page1Component);
    component = fixture.componentInstance;
    fixture.detectChanges();
    todosService = TestBed.inject(TodosService);
  });
 
  it('should fill todos', () => {
    const todos = of([
      {
        completed: false,
        id: 1,
        title: 'title1',
        userId: 1,
      },
    ]);
    spyOn(todosService, 'getTodos').and.returnValue(todos);
    component.ngOnInit();
    expect(component.todos).toEqual(todos);
  });
});

I got the following error message:

Expected [ Object({ completed: false, id: 1, title: 'title1', userId: 1 }) ] to equal Observable({ _isScalar: false, _subscribe: Function }).

I try to use the following mock:

const todos = [
  {
    completed: false,
    id: 1,
    title: 'title1',
    userId: 1,
  },
];

But in this case i get the following popup in my IDE:

Argument of type '{ completed: boolean; id: number; title: string; userId: number; }[]' is not assignable to parameter of type 'Observable'.

Please, help me fix this unit-test

serrgg
  • 65
  • 4
  • It's unclear how your service is set up in the tests, but for one thing your test double is incorrect - the service returns an *observable* of the value. Please see https://angular.io/guide/testing-components-scenarios#component-with-async-service and give a [mre] if you still cannot fix it. If you're just asking how to make an observable of a value, this is a dupe of https://stackoverflow.com/q/35219713/3001761. – jonrsharpe Apr 18 '21 at 21:19

1 Answers1

1

You're pretty close with what you're trying, but you're comparing an array with an observable on the expect matcher. You need to compare the result from the observable

  const data = [
    {
      completed: false,
      id: 1,
      title: 'title1',
      userId: 1,
    },
  ]
  const todosObservable = of(data);
  spyOn(todosService, 'getTodos').and.returnValue(todosObservable);
  component.ngOnInit();
  expect(component.todos).toEqual(data);

The above snippet will work fine, but I generally prefer using the HttpClientTestingModule, it's handy as you don't have to mock the services as often

Drenai
  • 11,315
  • 9
  • 48
  • 82