如何测试js的响应拦截器



我试图遵循这个线程,但它一直得到一个错误。

transform-response.interceptor.ts:

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiResponseInterface } from '@walletxp/shared-interfaces';
@Injectable()
export class TransformResponseInterceptor<T>
implements NestInterceptor<T, ApiResponseInterface<Record<string, unknown>>>
{
intercept(context: ExecutionContext, next: CallHandler): Observable<ApiResponseInterface<Record<string, unknown>>> {
return next.handle().pipe(map((data) => ({ success: true, data })));
}
}

对于它的测试,transform-response.interceptor.spec.ts:

import { TransformResponseInterceptor } from './transform-response.interceptor';
const interceptor = new TransformResponseInterceptor();
const executionContext: any = {
switchToHttp: jest.fn().mockReturnThis(),
getRequest: jest.fn().mockReturnThis(),
};
const callHandler = {
handle: jest.fn(),
};
describe('ResponseInterceptor', () => {
it('should be defined', () => {
expect(interceptor).toBeDefined();
});
describe('#intercept', () => {
it('t1', async () => {
(executionContext.switchToHttp().getRequest as jest.Mock<any, any>).mockReturnValueOnce({
body: { data: 'mocked data' },
});
callHandler.handle.mockResolvedValueOnce('next handle');
const actualValue = await interceptor.intercept(executionContext, callHandler);
expect(actualValue).toBe('next handle');
expect(executionContext.switchToHttp().getRequest().body).toEqual({
data: 'mocked data',
addedAttribute: 'example',
});
expect(callHandler.handle).toBeCalledTimes(1);
});
});
});

我的目标是模拟从控制器返回的数据,并检查它经过拦截器后是否等于我想要的格式化数据。

我将展示一个来自我的项目的简单而清晰的实际示例。这个例子类似于问题中显示的使用拦截器转换对象的例子。我使用这个拦截器从作为response发送的user对象中排除敏感属性,如hashedPassword:

describe('SerializerInterceptor', () => {
let interceptor: SerializerInterceptor
beforeEach(() => {
interceptor = new SerializerInterceptor(UserDto)
})
it('should return user object without the sensitive properties', async () => {
const context = createMock<ExecutionContext>()
const handler = createMock<CallHandler>({
handle: () => of(testUser)
})
const userObservable = interceptor.intercept(context, handler)
const user = await lastValueFrom(userObservable)
expect(user.id).toEqual(testUser.id)
expect(user.username).toEqual(testUser.username)
expect(user).not.toHaveProperty('hashedPassword')
})
})

为了模拟ExecutionContextCallHandler,我们使用了@golevelup/ts-jest包中的createMock()函数。

NestJSInterceptor底层使用RxJS。因此,当框架调用它的intercept()方法时,它返回对象的Observable。为了清晰地从这个Observable中提取我们的值,我们使用RxJS中的方便函数lastValueFrom()

testUser这里,是你的被测对象。您需要创建它,并如上所示将其提供给模拟处理程序。

我已经测试了我的拦截器,使用对应用程序的调用,更像是一个端到端测试。

import { Test, TestingModule } from '@nestjs/testing';
import * as request from 'supertest';
import { INestApplication, HttpStatus } from '@nestjs/common';
import { EmulatorHeadersInterceptor } from '@LIBRARY/interceptors/emulator-headers.interceptor';
import { AppModule } from '@APP/app.module';
describe('Header Intercepter', () => {
let app: INestApplication;
afterAll(async () => {
await app.close();
});
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
app.useGlobalInterceptors(new EmulatorHeadersInterceptor());
await app.init();
});
it('./test (PUT) should have the interceptor data', async () => {
const ResponseData$ = await request(app.getHttpServer())
.put('/test')
.send();
expect(ResponseData$.status).toBe(HttpStatus.OK);
expect(ResponseData$.headers['myheader']).toBe('interceptor');
});
});

我的拦截器正在添加一个头字段,但对于你的拦截器,你会用你的拦截器替换我正在使用的头拦截器。从这里,您可以测试响应是否包含您想要的内容。

如果您正在寻找一个简单的单元测试,那么您需要了解RxJS如何用于异步测试。可以使用如下命令:

describe('ResponseInterceptor', () => {
let interceptor: ResponseInterceptor;
beforeEach(() => {
interceptor = new ResponseInterceptor();
});
it('should map the data', (done) => {
// this sets up a mock execution context (which you don't use so it's blank)
// and a mock CallHandler that returns a known piece of data 'test data'
const obs$ = interceptor.intercept({} as any, { handle: () => of('test data') });
// this tests the observable, and calls done when it is complete
obs$.subscribe({
next: (val) => {
expect(val).toEqual({ success: true, data: 'test data' })
}),
complete: () => done()
})
});
});

相关内容

  • 没有找到相关文章

最新更新