#unit-testing #angular
#модульное тестирование #angular
Вопрос:
Я перешел с RC4 на финальную версию (2.1.0) и занимаюсь рефакторингом своих модульных тестов в соответствии с синтаксисом 2.1.0. Это легко, за исключением HTTP-макета.
Я не могу найти никаких примеров того, как имитировать HTTP-запросы в 2.1.0
Вот модульный тест HTTP RC4. Как бы мне переписать это в финальной версии 2.1.0?
it('ngOnInit()',
async(inject([TestComponentBuilder, XHRBackend], (tcb:TestComponentBuilder, mockBackend:MockBackend) => {
tcb.createAsync(Route1ListComponent).then((fix:ComponentFixture<Route1ListComponent>) => {
// THIS BLOCK OF CODE I NEED HELP TO RE-WRITE TO 2.1.0
mockBackend.connections.subscribe(
(connection:MockConnection) => {
connection.mockRespond(new Response(
new ResponseOptions({
body: persons
}
)));
});
// THIS BLOCK OF CODE WILL NOT CHANGE
let instance = fix.componentInstance;
instance.ngOnInit();
expect(instance.persons.length).toBe(3);
});
})));
ПРИМЕЧАНИЕ: Пожалуйста, НЕ предоставляйте RC-код. Спасибо
Ответ №1:
Первое, что вам нужно сделать, это настроить TestBed
. Больше ничего нет TestComponentBuilder
. С TestBed
помощью, это похоже на настройку @NgModule
с нуля, только для тестовой среды. Это означает, что вы добавите тестируемый компонент в declarations
, добавите любых поставщиков в provider
и любой импорт в imports
.
Чтобы настроить макет серверной части для Http
provider, вам просто нужно создать Http
из MockBackend
.
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ HttpModule ],
declarations: [ RouteListComponent ],
providers: [
MockBackend,
BaseRequestOptions,
{
provide: Http,
useFactory: (backend: MockBackend, options: BaseRequestOptions) => {
return new Http(backend, options);
},
deps: [ MockBackend, BaseRequestOptions ]
}
]
})
})
Это должно быть для конфигурации, предполагая, что вам не нужны другие поставщики или импорт, о которых я не знаю.
Для теста вы сначала захотите сделать его async
тестом, так как в тесте вы будете выполнять асинхронные операции. Это не изменилось с RC, вы просто используете async
. Если компонент использует templateUrl
(а вы не используете Webpack), то вам нужно будет вызвать TestBed.compileComponents()
, в противном случае нет необходимости. После этого вы можете создать компонент с TestBed.createComponent
let fixture: ComponentFixture<RouteListComponent>;
let component: RouteListComponent;
beforeEach(async(() => {
TestBed.configureTestingModule({ ... })
.compileComponents().then(() => {
fixture = TestBed.createComponent(RouteListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
it('...', async(inject([MockBackend], (backend: MockBackend) => {
})))
Практически все вышеперечисленное, связанное с тестированием, может быть импортировано из @angular/core/testing
. Ваше использование MockBackend
все равно будет таким же.
Еще одно замечание, вам не нужно вызывать component.ngOnInit
. Это вызывается фреймворком при вызове fixture.detectChanges()
Смотрите также:
- Документация по тестированию для более полного изучения поддержки тестирования.
Комментарии:
1. Большое спасибо за этот ответ, без него я не смог бы достичь своего решения, изложенного здесь. Мое решение основано на этом, но, правильно или неправильно, избегает использования .. async(inject([MockBackend], (backend: MockBackend) .. этот ответ был высоко оценен … еще раз большое спасибо 🙂 … если у вас есть какие-либо отзывы о моем окончательном решении, это было бы очень полезно … 1
Ответ №2:
Большое спасибо @peeskillet за помощь в получении моего ответа..
import {APP_BASE_HREF} from '@angular/common';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {AppModule} from '../../../app.module';
import {persons} from '../../../data/persons';
import {Route1ListComponent} from './route1-list.component';
// HTTP mocking imports
import {BaseRequestOptions, Http, Response, ResponseOptions} from '@angular/http';
import {MockBackend, MockConnection} from '@angular/http/testing';
describe('route1-list.component.ts', () => {
let fix: ComponentFixture<Route1ListComponent>;
let instance: Route1ListComponent;
let injector: any;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [AppModule],
providers: [{provide: APP_BASE_HREF, useValue: '/'},
MockBackend,
BaseRequestOptions,
{
provide: Http,
useFactory: (pBackend: MockBackend, pOptions: BaseRequestOptions) => {
return new Http(pBackend, pOptions);
},
deps: [MockBackend, BaseRequestOptions]
}]
}).compileComponents()
.then(() => {
fix = TestBed.createComponent(Route1ListComponent);
instance = fix.componentInstance;
injector = fix.debugElement.injector;
});
}));
it('should instantiate component', () => {
expect(instance).toEqual(jasmine.any(Route1ListComponent));
});
it('should have expected text', () => {
let el = fix.debugElement.query(By.css('section.route1-list')).nativeElement;
expect(el.textContent).toMatch(/route 1 list view/i, 'should have expected text');
});
it('ngOnInit()', async(() => {
let backend = injector.get(MockBackend);
backend.connections.subscribe(
(connection: MockConnection) => {
connection.mockRespond(new Response(
new ResponseOptions({
body: persons
}
)));
});
fix.detectChanges(); // Calls instance.ngOnInit()
expect(instance.persons.length).toBe(3);
}));
it('ngOnInit() failure', async(() => {
let backend = injector.get(MockBackend);
backend.connections.subscribe(
(connection: MockConnection) => {
connection.mockError(new Error('error'));
});
fix.detectChanges(); // Calls instance.ngOnInit()
expect(instance.persons).toBeUndefined();
}));
});
Обратите внимание, что на момент написания Angular2 docs at ..
https://angular.io/docs/ts/latest/api/http/testing/index/MockBackend-class.html
https://angular.io/docs/ts/latest/api/http/testing/index/MockConnection-class.html
кажется, это неправильно.
Когда я использую Injector.resolveAndCreate
, как описано в документах, я получаю сообщение об ошибке:
Свойство ‘resolveAndCreate’ не существует для типа ‘typeof Injector’.
Чтобы исправить это, мне пришлось основывать свой ответ на ответе, предоставленном @peeskillet