Дразнить сервис для вызова локального json-сервера вместо удаленной конечной точки - проверить синтаксис? (Угловой 2)

Я пытаюсь написать модульный тест, чтобы определить, что свойство моего углового компонента 2 заполняется после вызова службы, которая возвращает обещание.

Мой компонент содержит метод:

getListItems() {
  this.employeeService.loadEmployees().then(res => {
    this._employees = res['Employees'];
    this.ref.markForCheck();
   });
};

Это вызывает метод службы:

@Injectable()
export class EmployeeService {

  constructor(
    public http: Http
  ) { }
  
  public loadEmployees(): Promise<any> {
    return this.http.get('employees.json')
      .map((res: Response) => res.json())
      .toPromise();
  }
}

Который извлекает содержимое из локального файла JSON (вместо создания удаленной конечной точки). Это работает достаточно хорошо, но я бы хотел заменить сервисный метод при тестировании на метод, который делает вызов локальному json-серверу.

Насколько я могу судить, у меня при запуске тестов Karma правильно вращается / падает json-сервер - я могу использовать Postman, чтобы успешно выполнить запрос GET, пока тесты выполняются.

Поэтому я хотел бы заменить мой сервис на макет:

class MockEmployeeService {
  headers: Headers;

  constructor(private http: Http) {
    this.headers = new Headers({ 'Content-Type': 'application/json' });
  }

  public loadEmployees() {
    return this.http.get('http://localhost:3004/getEmployees',
      {headers: this.headers, body: '' })
     .map((res: Response) => res.json());
 }
}

и я настроил модульный тест следующим образом:

describe('ListComponent', () => {

  let fixture;
  let component;
  let employeeService;

  beforeEach( async(() => {

 TestBed.configureTestingModule({
   imports: [
  HttpModule
   ],
   declarations: [
  ListComponent
   ],
   providers: [
     {provide: EmployeeService, useClass: MockEmployeeService}
   ]
    })
    .compileComponents();
  }));

  beforeEach(() => {

 fixture = TestBed.createComponent(ListComponent);
 component = fixture.componentInstance;

 employeeService = fixture.debugElement.injector
      .get(EmployeeService);
 });

  it('should retrieve test values from json-server (async)',
    async(() => {
   fixture.detectChanges();
   component.getListItems();
   fixture.whenStable.then(() => {
  expect(component._employees).toBeDefined();
   });
  }));
})

Поэтому (я думаю) я вызываю метод в компоненте, который должен вызывать сервис, который должен быть заменен на MockEmployeeService, Я получаю следующую ошибку кармы:

× should retrieve test values from json-server (async)
  PhantomJS 2.1.1 (Windows 7 0.0.0)
Failed: Can't resolve all parameters for MockEmployeeService: (?).

На данный момент я в значительной степени нахожусь на границе своих знаний, и у меня возникают проблемы с поиском онлайн-ресурсов для новых тестов, использующих TestBed. Кто-нибудь может обнаружить здесь что-нибудь, что смотрит в сторону?

1 ответ

Решение

Если вы издеваетесь над сервисом, вы не должны использовать Http, Просто верни свое обещание, не взаимодействуя с Http,

class MockEmployeeService {
  public loadEmployees() {
    return Promise.resolve({some:'object'});
  }
}

С Http служба, вы будете делать вызов XHR, что вы не хотите делать во время теста. Для макетов мы хотим сделать его максимально простым, так как мы хотим, чтобы он влиял на тестируемый компонент как можно меньше.

Еще одна проблема с Http во время тестирования это то, что он зависит от браузера платформы, который недоступен в тестовой среде. Это не значит, что мы не можем его использовать. Нам просто нужно использовать вспомогательный класс, который Angular предоставляет для тестирования.

Мы рассмотрели макетирование сервиса для тестирования компонентов, но если вы также хотите протестировать свой сервис, вам нужно создать Http провайдер самостоятельно, используя некоторый класс вспомогательного теста Angular MockBackend,

TestBed.configureTestingModule({
  providers: [
    {
      provide: Http, useFactory: (backend, options) => {
        return new Http(backend, options);
      },
      deps: [MockBackend, BaseRequestOptions]
    },
    MockBackend,
    BaseRequestOptions
  ]
});

С MockBackendМы можем подписаться на связи и издеваться над ответами. Для полного примера этого, пожалуйста, смотрите этот пост

Смотрите также:

Другие вопросы по тегам