Only the code in the class-under-test should be exercised. In case of the CurrentWeatherComponent, we need to ensure that the service code is not executed. For this reason, you should never provide the actual implementation of the service. This is also why we used HttpClientTestingModule in the previous section. Since this is our custom service, we must provide our own implementation of a test double.
In this case, we will implement a fake of the service. Since the fake of the WeatherService will be used in tests for multiple components, your implementation should be in a separate file. For the sake of maintainability and discoverability of your code base, one class per file is a good rule of thumb to follow. Keeping classes in separate files will save you from committing certain coding sins, like mistakenly creating or sharing global state or standalone functions between two classes, keeping your code properly decoupled in the process:
- Create a new file weather/weather.service.fake.ts
We need to ensure that APIs for the actual implementation and the test double don't go out of sync over time. We can accomplish this by creating an interface for the service.
- Add IWeatherService to weather.service.ts, as shown:
src/app/weather/weather.service.ts
export interface IWeatherService {
getCurrentWeather(city: string, country: string): Observable<ICurrentWeather>
}
- Update WeatherService so that it implements the new interface:
src/app/weather/weather.service.ts
export class WeatherService implements IWeatherService
- Implement a basic fake in weather.service.fake.ts, as follows:
src/app/weather/weather.service.fake.ts
import { Observable, of } from 'rxjs'
import { IWeatherService } from './weather.service'
import { ICurrentWeather } from '../interfaces'
export class WeatherServiceFake implements IWeatherService {
private fakeWeather: ICurrentWeather = {
city: 'Bursa',
country: 'TR',
date: 1485789600,
image: '',
temperature: 280.32,
description: 'light intensity drizzle',
}
public getCurrentWeather(city: string, country: string): Observable<ICurrentWeather> {
return of(this.fakeWeather)
}
}
Now you're ready to provide the fake to AppComponent and CurrentWeatherComponent.
- Update providers for both components to use WeatherServiceFake
so that the fake will be used instead of the actual service:
src/app/app.component.spec.ts
src/app/current-weather/current-weather.component.spec.ts
...
beforeEach(
async(() => {
TestBed.configureTestingModule({
...
providers: [{ provide: WeatherService, useClass: WeatherServiceFake}],
...
We have successfully resolved all configuration and setup related issues with our unit tests. Now, we need to fix the unit tests that were generated with the initial code.