2

I have a simple service method that does an http post call to add a todoList:

add(event: any): Observable<TodoList> {
    let todoListToAdd: TodoList = { name: event.target.value, listItems: []};
    return this.http.post<TodoList>("https://localhost:44305/todolist", todoListToAdd);
}

I want to unit test this method and tried like this:

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

import { TodolistService } from './todolist.service';
import { TodoList } from './todolist';
import { HttpResponse } from '@angular/common/http';

describe('TodolistService', () => {
  let injector: TestBed;
  let service: TodolistService;
  let httpMock: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [ HttpClientTestingModule ],
      providers: [ TodolistService ]
    });

    injector = getTestBed();
    service = injector.get(TodolistService);
    httpMock = injector.get(HttpTestingController);
  });

  afterEach(() => {
    httpMock.verify();
  });

  describe('#getTodoLists', () => {
     it('getTodoLists - when called after add was called once, then it should return 3 todo lists', () => {
      const event = { target: { value: "test" } };
      const expectedTodoList: TodoList = { name: event.target.value, listItems: []};

      service.add(event);
  
      const req = httpMock.expectOne("https://localhost:44305/todolist");
      expect(req.request.method).toBe("POST");
      expect(req.request.body).toEqual(expectedTodoList);
      req.flush(expectedTodoList);
    });
  });
});

Why am I getting the following error?

Error: Expected one matching request for criteria "Match URL: https://localhost:44305/todolist", found none.

It is exactly the url that I am calling in the add method, why doesn't it find it?

Thanks in advance for your help

xeraphim
  • 4,375
  • 9
  • 54
  • 102

1 Answers1

4

While all your mocks and imports are perfectly fine, you forgot to subscribe to the returned observable. This is important for the underlaying method to actually run. To make it work just subscribe to the stream and inside run your assertions.

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

import { TodolistService } from './todolist.service';
import { TodoList } from './todolist';
import { HttpResponse } from '@angular/common/http';

describe('TodolistService', () => {
  let injector: TestBed;
  let service: TodolistService;
  let httpMock: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [ HttpClientTestingModule ],
      providers: [ TodolistService ]
    });

    injector = getTestBed();
    service = injector.get(TodolistService);
    httpMock = injector.get(HttpTestingController);
  });

  afterEach(() => {
    httpMock.verify();
  });

  describe('#getTodoLists', () => {
    it('getTodoLists - when called after add was called once, then it should return 3 todo lists', () => {
      const event = { target: { value: "test" } };
      const expectedTodoList: TodoList = { name: event.target.value, listItems: []};

      service.add(event).subscribe((todoList) => {
        expect(todoList).toEqual(expectedTodoList);
      });

      const req = httpMock.expectOne("https://localhost:44305/todolist");
      expect(req.request.method).toBe("POST");
      expect(req.request.body).toEqual(expectedTodoList);
      req.flush(expectedTodoList); // This will actually "run" the mocked request if there are any subscribers
    });
  });
});
Philipp Meissner
  • 5,273
  • 5
  • 34
  • 59
  • thanks, that helped a bit but the test still fails unfortunately. Now (with the subscribe and the done) I get these errors: Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL) Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL) at Error: Expected no open requests, found 1: POST https://localhost:44305/todolist Shouldnt the httpMock.verify() make sure, that there are no open requests? – xeraphim Jul 30 '20 at 07:12
  • Ah, my bad. Updated my answer. It's been some time since I worked on this part of the tests. – Philipp Meissner Jul 30 '20 at 07:24