Ana içeriğe geç

Angular uygulamasında bir HTTP interceptor nasıl test edilir

Bir interceptor'ı test etmek için interceptor'ın kendisine ve modülüne ihtiyacımız var. Interceptor useValue veya useFactory ile tanımlanmışsa, refaktoring yapmayı dikkate alın; useClass ve useExisting desteklenmektedir.

ipucu

useValue ve useFactory'nin problemleri, diğer interceptor'ların TestBed üzerindeki etkisini önlemek için ayırt edilmesinin zor olmasıdır.

Interceptor, HTTP_INTERCEPTORS token'ı ile tanımlandığı için bunu korumamız gerekiyor. Ancak, bu diğer tüm interceptor'ların da korunmasına neden olur; bu yüzden NG_MOCKS_INTERCEPTORS token'ını hariç tutarak onlardan kurtulmamız gerekiyor. Buradaki sorun, daha fazla interceptor varsa, bu interceptor'ların sahte kopyalarının "Bir akış beklenirken 'undefined' sağladınız." hatasıyla başarısız olmasıdır.

tehlike

Son önemli adım, HttpClientModule'u HttpClientTestingModule ile değiştirmektir, böylece istekleri sahtelemek için HttpTestingController kullanabiliriz.

beforeEach(() =>
MockBuilder(TargetInterceptor, TargetModule)
.exclude(NG_MOCKS_INTERCEPTORS)
.keep(HTTP_INTERCEPTORS)
.replace(HttpClientModule, HttpClientTestingModule)
);

TargetInterceptor'ın her isteğe My-Custom: HttpInterceptor başlığını eklediğini varsayalım. Bunu test etmek için HttpClient aracılığıyla bir istek göndermemiz gerekiyor.

const client = TestBed.get(HttpClient);

client.get('/target').subscribe();

Bir sonraki adım, isteğin beklentisini yazmaktır.

const req = httpMock.expectOne('/target');

req.flush('');
httpMock.verify();

Artık isteğin başlıklarını doğrulayabiliriz.

expect(req.request.headers.get('My-Custom')).toEqual(
'HttpInterceptor'
);

Canlı örnekler

https://github.com/help-me-mom/ng-mocks/blob/master/examples/TestHttpInterceptor/test.spec.ts
import {
HTTP_INTERCEPTORS,
HttpClient,
HttpClientModule,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
} from '@angular/common/http';
import {
HttpClientTestingModule,
HttpTestingController,
} from '@angular/common/http/testing';
import { Injectable, NgModule } from '@angular/core';
import { Observable } from 'rxjs';

import {
MockBuilder,
MockRender,
NG_MOCKS_INTERCEPTORS,
ngMocks,
} from 'ng-mocks';

// Test etmek istediğimiz bir interceptor.
@Injectable()
class TargetInterceptor implements HttpInterceptor {
protected value = 'HttpInterceptor';

public intercept(
request: HttpRequest<void>,
next: HttpHandler,
): Observable<HttpEvent<void>> {
return next.handle(
request.clone({
setHeaders: {
'My-Custom': this.value,
},
}),
);
}
}

// Görmezden gelmek istediğimiz bir interceptor.
@Injectable()
class MockInterceptor implements HttpInterceptor {
protected value = 'Ignore';

public intercept(
request: HttpRequest<void>,
next: HttpHandler,
): Observable<HttpEvent<void>> {
return next.handle(
request.clone({
setHeaders: {
'My-Mock': this.value,
},
}),
);
}
}

// Tanımını içeren bir modül.
@NgModule({
imports: [HttpClientModule],
providers: [
TargetInterceptor,
MockInterceptor,
{
multi: true,
provide: HTTP_INTERCEPTORS,
useExisting: TargetInterceptor,
},
{
multi: true,
provide: HTTP_INTERCEPTORS,
useClass: MockInterceptor,
},
],
})
class TargetModule {}

describe('TestHttpInterceptor', () => {
// Interceptor'ı test etmek istediğimiz için, onu MockBuilder'ın ilk parametresi olarak geçiriyoruz.
// Bağımlılıklarını doğru bir şekilde yerine getirmek için, modülünü ikinci parametre olarak geçmemiz gerekiyor.
// Ayrıca, `.mock` içine HTTP_INTERCEPTORS geçirmeli ve
// HttpClientModule'u HttpClientTestingModule ile değiştirmeliyiz.
beforeEach(() => {
return MockBuilder(TargetInterceptor, TargetModule)
.exclude(NG_MOCKS_INTERCEPTORS)
.keep(HTTP_INTERCEPTORS)
.replace(HttpClientModule, HttpClientTestingModule);
});

it('interceptor\'ı tetikler', () => {
MockRender();

// Test için hizmeti ve http denetleyicisini çıkaralım.
const client = ngMocks.findInstance(HttpClient);
const httpMock = ngMocks.findInstance(HttpTestingController);

// Basit bir istek yapalım.
client.get('/target').subscribe();

// Şimdi isteğe bir başlığın eklendiğini doğrulayabiliriz.
const req = httpMock.expectOne('/target');
req.flush('');
httpMock.verify();

expect(req.request.headers.get('My-Custom')).toEqual(
'HttpInterceptor',
);
});
});