如何模拟一个对象并验证给定的参数是否提供给了这个模拟
How to mock an object and verify a given parameter was provided to this mock
我在 ng-mocks
:
的帮助下尝试测试一个 HttpInterceptor
@Injectable()
export class AuthTokenInterceptor implements HttpInterceptor {
constructor(private store: Store) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const currentToken = this.store.selectSnapshot(state => state.accounts.accessToken);
if (currentToken) {
req = req.clone({
setHeaders: { Authorization: `Bearer ${currentToken}` },
});
}
return next.handle(req);
}
}
我无法了解如何提供 next
参数,特别是因为我想检查对象是否具有 setHeaders 属性 存在(或不存在):
describe('Unauth guard test', () => {
beforeEach(() => {
return MockBuilder(AuthTokenInterceptor, AppModule).mock(Store);
});
it('should allow access if not authenticated', () => {
//Arrange
const fakeToken = 'fakeToken';
const storeDispatchSpy = MockInstance(Store, 'selectSnapshot', jasmine.createSpy().and.returnValue(fakeToken));
const httpHandlerSpy = MockInstance(HttpHandler, 'handle', jasmine.createSpy().and.returnValue(fakeToken));
const fixture = MockRender(AuthTokenInterceptor);
const interceptor = fixture.point.componentInstance;
const request = new HttpRequest('GET', 'http://localhost:4200/');
//Act
const result = interceptor.intercept(request, httpHandlerSpy.???);//How to provide a mock of HttpHandler?
//Assert
expect(storeDispatchSpy).toHaveBeenCalled();
expect(httpHandlerSpy).toHaveBeenCalledOnceWith(???);//How to verify that one parameter of the HttpRequest is set to specific value?
});
});
但是如何为拦截方法提供模拟实例?更复杂的是,如何检查我的间谍是否已使用具有特定值的对象调用?
在您的情况下,您需要提供 mockStore
+ 将您的拦截器与其他拦截器隔离。
来自 ng-mocks
docs and http interceptors 的示例。
https://codesandbox.io/s/intelligent-stallman-9bwup0?file=/src/test.spec.ts
describe('AuthTokenInterceptor', () => {
beforeEach(() => {
return (
MockBuilder(AuthTokenInterceptor, AppModule)
// required for interceptors
.exclude(NG_MOCKS_INTERCEPTORS)
.keep(HTTP_INTERCEPTORS)
.replace(HttpClientModule, HttpClientTestingModule)
);
});
it('adds header', () => {
// creating an empty fixture
const fixture = MockRender('', null, false);
// stubbing store
const store = ngMocks.findInstance(Store);
ngMocks.stubMember(store, 'selectSnapshot', callback =>
callback({
accounts: {
accessToken: 'Testing',
},
}),
);
// render
fixture.detectChanges();
// instances to test how HttpClient uses interceptors
const client = ngMocks.findInstance(HttpClient);
const httpMock = ngMocks.findInstance(HttpTestingController);
// Let's do a simple request.
client.get('/target').subscribe();
// Now we can assert that a header has been added to the request.
const req = httpMock.expectOne('/target');
req.flush('');
httpMock.verify();
// asserting headers
expect(req.request.headers.get('Authorization')).toEqual(
'Bearer Testing',
);
});
});
我在 ng-mocks
:
HttpInterceptor
@Injectable()
export class AuthTokenInterceptor implements HttpInterceptor {
constructor(private store: Store) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const currentToken = this.store.selectSnapshot(state => state.accounts.accessToken);
if (currentToken) {
req = req.clone({
setHeaders: { Authorization: `Bearer ${currentToken}` },
});
}
return next.handle(req);
}
}
我无法了解如何提供 next
参数,特别是因为我想检查对象是否具有 setHeaders 属性 存在(或不存在):
describe('Unauth guard test', () => {
beforeEach(() => {
return MockBuilder(AuthTokenInterceptor, AppModule).mock(Store);
});
it('should allow access if not authenticated', () => {
//Arrange
const fakeToken = 'fakeToken';
const storeDispatchSpy = MockInstance(Store, 'selectSnapshot', jasmine.createSpy().and.returnValue(fakeToken));
const httpHandlerSpy = MockInstance(HttpHandler, 'handle', jasmine.createSpy().and.returnValue(fakeToken));
const fixture = MockRender(AuthTokenInterceptor);
const interceptor = fixture.point.componentInstance;
const request = new HttpRequest('GET', 'http://localhost:4200/');
//Act
const result = interceptor.intercept(request, httpHandlerSpy.???);//How to provide a mock of HttpHandler?
//Assert
expect(storeDispatchSpy).toHaveBeenCalled();
expect(httpHandlerSpy).toHaveBeenCalledOnceWith(???);//How to verify that one parameter of the HttpRequest is set to specific value?
});
});
但是如何为拦截方法提供模拟实例?更复杂的是,如何检查我的间谍是否已使用具有特定值的对象调用?
在您的情况下,您需要提供 mockStore
+ 将您的拦截器与其他拦截器隔离。
来自 ng-mocks
docs and http interceptors 的示例。
https://codesandbox.io/s/intelligent-stallman-9bwup0?file=/src/test.spec.ts
describe('AuthTokenInterceptor', () => {
beforeEach(() => {
return (
MockBuilder(AuthTokenInterceptor, AppModule)
// required for interceptors
.exclude(NG_MOCKS_INTERCEPTORS)
.keep(HTTP_INTERCEPTORS)
.replace(HttpClientModule, HttpClientTestingModule)
);
});
it('adds header', () => {
// creating an empty fixture
const fixture = MockRender('', null, false);
// stubbing store
const store = ngMocks.findInstance(Store);
ngMocks.stubMember(store, 'selectSnapshot', callback =>
callback({
accounts: {
accessToken: 'Testing',
},
}),
);
// render
fixture.detectChanges();
// instances to test how HttpClient uses interceptors
const client = ngMocks.findInstance(HttpClient);
const httpMock = ngMocks.findInstance(HttpTestingController);
// Let's do a simple request.
client.get('/target').subscribe();
// Now we can assert that a header has been added to the request.
const req = httpMock.expectOne('/target');
req.flush('');
httpMock.verify();
// asserting headers
expect(req.request.headers.get('Authorization')).toEqual(
'Bearer Testing',
);
});
});