Fixing the tests and understanding TestBed – Design for Tests: Best Practices

To better understand the use of TestBed, we’ll fix the rest of our project’s tests by adding dependencies to the test files. We’ll start with the app.component.spec.ts file and make the fixes as follows:
describe(‘AppComponent’, () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
     declarations: [AppComponent],
     imports: [RouterTestingModule],
   }).compileComponents();
  });
  it(‘should create the app’, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });
});

In this test, we cleaned up the test cases that had already been created by the Angular CLI when we started the project. It has the router-outlet component so we need to mock Angular’s route services. Like the HttpClient service, the Angular team has also prepared a specific module for testing, and so we are importing the RouterTestingModule module here.

We’ll change the test in the login.component.spec.ts file next:
beforeEach(() => {
  TestBed.configureTestingModule({
    declarations: [LoginComponent],
    imports: [ReactiveFormsModule],
    providers: [
      AuthService,
      {
        provide: AuthService,
        useValue: jasmine.createSpyObj(‘AuthService’, [‘login’]),
      },
    ],
  });
  fixture = TestBed.createComponent(LoginComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

Since the Login component relies on the ReactiveFormsModule module, we also need to import it into our test. Furthermore, the component utilizes the AuthService service, and for our mocking purposes, we employ the useValue property, as demonstrated earlier. In unit testing, it’s crucial to concentrate on the component itself, and we achieve this by isolating it through the mocking of its dependencies.

The next test to tune will be for the home.component.spec.ts file:
beforeEach(() => {
  TestBed.configureTestingModule({
    declarations: [HomeComponent],
    imports: [RouterTestingModule],
    providers: [
      AuthService,
      {
        provide: AuthService,
        useValue: jasmine.createSpyObj(‘AuthService’, [‘logout’]),
      },
    ],
  });
  fixture = TestBed.createComponent(HomeComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

When testing the Home component, we need to include the ‘RouterTestingModule’ dependency because we are using route services and we are mocking the ‘AuthService’ service due to the application’s logout action.

Next, let’s fix the test for the new-entry-form-template.component.spec.ts file:
beforeEach(() => {
  TestBed.configureTestingModule({
    declarations: [NewEntryFormTemplateComponent],
    imports: [FormsModule],
    providers: [
      ExerciseSetsService,
      {
        provide: ExerciseSetsService,
        useValue: jasmine.createSpyObj(‘ExerciseSetsService’, [‘addNewItem’]),
      },
    ],
  });
  fixture = TestBed.createComponent(NewEntryFormTemplateComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

This page employs template-driven form techniques, so for the test run, we include the ‘FormsModule’ module by importing it. As it only uses the ‘ExerciseSetsService’ service, we mocked it with the help of the Jasmine framework.

We’ll work on testing the new-entry-form-reactive.component.spec page next:
beforeEach(() => {
  TestBed.configureTestingModule({
    declarations: [NewEntryFormReactiveComponent],
    imports: [ReactiveFormsModule, RouterTestingModule],
    providers: [
      ExerciseSetsService,
      {
        provide: ExerciseSetsService,
        useValue: jasmine.createSpyObj(‘ExerciseSetsService’, [
          ‘addNewItem’,
          ‘updateItem’,
        ]),
      },
      ExercisesService,
      {
        provide: ExercisesService,
        useValue: jasmine.createSpyObj(‘ExercisesService’, [‘getExercises’]),
      },
    ],
  });
  fixture = TestBed.createComponent(NewEntryFormReactiveComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

In Chapter 9, Exploring Reactivity with RxJS, we incorporated the search exercise into the form, so in this test case, we need to import the ‘ReactiveFormsModule’ and ‘RouterTestingModule’ modules. In addition, we need to mock the ‘ExerciseSetsService’ and ‘ExercisesService’ services.

With this test set, let’s go to the last component, diary.component.spec.ts:
describe(‘DiaryComponent’, () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [
        DiaryComponent,
        ListEntriesComponent,
        NewItemButtonComponent,
      ],
      imports: [RouterTestingModule],
      providers: [
        ExerciseSetsService,
        {
          provide: ExerciseSetsService,
          useValue: jasmine.createSpyObj(‘ExerciseSetsService’, [
            ‘deleteItem’
          ]),
        },
      ],
    }).compileComponents();
    fixture = TestBed.createComponent(DiaryComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });
});

This component, as it is a smart component in our suggested architecture, needs to declare the components that compose it in your test. Here, they are DiaryComponent, ListEntriesComponent, and NewItemButtonComponent. Finally, we imported the RouterTestingModule module into the test setup and mocked up the ExerciseSetsService service, thus correcting all the tests in our project.

To understand how TestBed works, let’s create a test case for our component.

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