官术网_书友最值得收藏!

Test doubles

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:

  1. 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.

  1. Add IWeatherService to weather.service.ts, as shown:
src/app/weather/weather.service.ts
export interface IWeatherService {
getCurrentWeather(city: string, country: string): Observable<ICurrentWeather>
}
  1. Update WeatherService so that it implements the new interface:
src/app/weather/weather.service.ts
export class WeatherService implements IWeatherService
  1. 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)
}
}

We're leveraging the existing ICurrentWeather interface that our fake data is correctly shaped, but we must also turn it into an Observable. This is easily achieved using of, which creates an observable sequence, given the provided arguments.

Now you're ready to provide the fake to AppComponent and CurrentWeatherComponent.

  1. 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}],
...

As your services and components get more complicated, it's easy to provide an incomplete or inadequate test double. You may see errors such as NetworkError: Failed to execute 'send' on 'XMLHttpRequest', Can't resolve all parameters, or [object ErrorEvent] thrown. In case of the latter error, click on the Debug button in Karma to discover the view error details, which may look like Timeout - Async callback was not invoked within timeout specified by jasmine. Unit tests are designed to run in milliseconds, so it should be impossible to actually hit the default 5-second timeout. The issue is almost always with the test setup or configuration.

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.

主站蜘蛛池模板: 玛沁县| 教育| 晴隆县| 德惠市| 江油市| 宁陕县| 明水县| 平顺县| 峨眉山市| 利津县| 平山县| 阳西县| 星子县| 乐山市| 舟山市| 德格县| 北宁市| 南部县| 和硕县| 青冈县| 郓城县| 和龙市| 剑川县| 景泰县| 霍林郭勒市| 长白| 彭泽县| 广平县| 黔西县| 红原县| 石阡县| 莱西市| 延寿县| 从江县| 双流县| 闵行区| 兴仁县| 海盐县| 开原市| 秀山| 吉隆县|