Service tests – Design for Tests: Best Practices-2

In this test case, part of the setup was done in the beforeEach function, but note that, instead, we must put the setup common to all test cases that will be executed to avoid slowdowns in the test cases. In the test in question, we defined a fake return from our server, since the unit tests must be executed independently of the backend service. In the execution phase, we call the service with the getInitialList method.

We call the subscribe method of the observable that the service returns, and inside it, we make the assertion that we expect the return to be equal to the item element of the fakeBody object. Here, the assertion phase can be tricky because, to check the return of this observable, we need to simulate the backend processing of the project.

Enter the Angular HttpTestingController service, with which we can emulate a response from our backend service. Here, we also create an assertion to ensure that our method is calling the API with the GET HTTP verb. In order to simulate the HTTP request , we use the flush method of the service and what we want to send – in this case, the fakebody object. But we need to remember that an HTTP operation is asynchronous so we use the tick function, available within the context of the fakeAsync function, to simulate the time that would pass for an asynchronous execution.

We will create a test for the same service to simulate the creation of a new entry:
it(‘should use the method addNewItem to add a new Entry’, fakeAsync(() => {
  const fakeBody: ExerciseSet = {
    id: ‘1’,
    date: new Date(),
    exercise: ‘Deadlift’,
    reps: 15,
    sets: 4,
  };
  service.addNewItem(fakeBody).subscribe((response) => {
    expect(response).toEqual(fakeBody);
  });
  const request = httpMock.expectOne((req) => {
    return req.method === ‘POST’;
  });
  request.flush(fakeBody);
  tick();
}));

We start with the definition of the new test that will appear in Karma and then we create the test function, again within the context of the fakeAsync function.

In the test setup, we define an object called fakeBody with the payload we want to send and make the assertion. In the execution phase of the method we want to test, we call the addNewItem method and place the assertion inside the subscribe function. We perform the assertion of the POST verb, and finally, we simulate the request using the flush and tick functions.

To end this session, let’s switch the fdescribe function to the describe function. In the test file of the ExercisesService, AuthInterceptor, and AuthService services, let’s make the following change:
beforeEach(() => {
  TestBed.configureTestingModule({ imports: [HttpClientTestingModule] });
});

As we saw in this section, we need to inform Angular of the test’s dependency, that is, declaring HttpClientTestingModule in the configuration of the TestBed component.

We still have to correct the test of the NotificationInterceptor service, which uses an external library as a dependency. We will refactor the notification.interceptor.spec.ts file as follows:
describe(‘NotificationInterceptor’, () => {
  beforeEach(() =>
    TestBed.configureTestingModule({
      providers: [
        NotificationInterceptor,
        {
          provide: ToastrService,
          useValue: jasmine.createSpyObj(‘ToastrService’, [‘success’]),
        },
      ],
    })
  );
});

In the case of general dependencies that we need to simulate in our tests, we can define the service in the providers property in the TestBed class definition. But instead of offering the original ToastrService class, we declare an object and, using the useValue property, it tells Angular which class to provide for the test.

Here, we could create a class that has the same original methods, but better than that, we are using a feature of the Jasmine test framework, which is the spy objects. With them, we can mock entire classes for our tests, thus managing to simulate unit test dependencies.

In the next section, we’ll fix all the tests and understand how Angular’s TestBed component works.

Leave a Reply

Your email address will not be published. Required fields are marked *

Privacy Policy | Cookie Policy | Cookies Settings | Terms & Conditions | Accessibility | Legal Notice