Jestjs NestJs请求和响应拦截器单元测试
我想为我的API记录传入请求和传出响应。我创建了一个请求拦截器和一个响应拦截器,如下所述 因此请求拦截器只记录请求对象Jestjs NestJs请求和响应拦截器单元测试,jestjs,nestjs,Jestjs,Nestjs,我想为我的API记录传入请求和传出响应。我创建了一个请求拦截器和一个响应拦截器,如下所述 因此请求拦截器只记录请求对象 @Injectable() export class RequestInterceptor implements NestInterceptor { private readonly logger: Logger = new Logger(RequestInterceptor.name, true); public intercept(context: Execut
@Injectable()
export class RequestInterceptor implements NestInterceptor {
private readonly logger: Logger = new Logger(RequestInterceptor.name, true);
public intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const { originalUrl, method, params, query, body } = context.switchToHttp().getRequest();
this.logger.debug({ originalUrl, method, params, query, body }, this.intercept.name);
return next.handle();
}
}
@Injectable()
导出类RequestInterceptor实现了NestInterceptor{
私有只读记录器:记录器=新记录器(RequestInterceptor.name,true);
公共截获(上下文:ExecutionContext,下一步:CallHandler):可观察{
const{originalUrl,method,params,query,body}=context.switchToHttp().getRequest();
debug({originalUrl,method,params,query,body},this.intercept.name);
返回next.handle();
}
}
响应拦截器等待传出响应,稍后记录状态代码和响应对象
@Injectable()
export class ResponseInterceptor implements NestInterceptor {
private readonly logger: Logger = new Logger(ResponseInterceptor.name, true);
public intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const { statusCode } = context.switchToHttp().getResponse();
return next.handle().pipe(
tap((responseData: any) =>
this.logger.debug({ statusCode, responseData }, this.intercept.name),
),
);
}
}
@Injectable()
导出类响应Interceptor实现NestInterceptor{
专用只读记录器:记录器=新记录器(ResponseInterceptor.name,true);
公共截获(上下文:ExecutionContext,下一步:CallHandler):可观察{
const{statusCode}=context.switchToHttp().getResponse();
返回next.handle().pipe(
点击((响应数据:任何)=>
this.logger.debug({statusCode,responseData},this.intercept.name),
),
);
}
}
我想测试他们,但不幸的是,我几乎没有测试经验。我试着从请求拦截器开始,然后想出了这个
const executionContext: any = {
switchToHttp: jest.fn().mockReturnThis(),
getRequest: jest.fn().mockReturnThis(),
};
const nextCallHander: CallHandler<any> = {
handle: jest.fn(),
};
describe('RequestInterceptor', () => {
let interceptor: RequestInterceptor;
beforeEach(() => {
interceptor = new RequestInterceptor();
});
describe('intercept', () => {
it('should fetch the request object', (done: any) => {
const requestInterception: Observable<any> = interceptor.intercept(executionContext, nextCallHander);
requestInterception.subscribe({
next: value => {
// ... ??? ...
},
error: error => {
throw error;
},
complete: () => {
done();
},
});
});
});
});
const executionContext: any = {
switchToHttp: jest.fn().mockReturnThis(),
getResponse: jest.fn().mockReturnThis()
};
const nextCallHander: CallHandler<any> = {
handle: jest.fn()
};
describe("ResponseInterceptor", () => {
let interceptor: ResponseInterceptor;
beforeEach(() => {
interceptor = new ResponseInterceptor();
});
describe("intercept", () => {
it("should fetch the statuscode and response data", (done: any) => {
const responseInterception: Observable<any> = interceptor.intercept(
executionContext,
nextCallHander
);
responseInterception.subscribe({
next: value => {
// ...
},
error: error => {
throw error;
},
complete: () => {
done();
}
});
});
});
});
const executionContext:any={
switchToHttp:jest.fn().mockReturnThis(),
getRequest:jest.fn().mockReturnThis(),
};
const nextCallHander:CallHandler={
句柄:jest.fn(),
};
描述('RequestInterceptor',()=>{
let拦截器:请求拦截器;
在每个之前(()=>{
拦截器=新请求拦截器();
});
描述('intercept',()=>{
它('应该获取请求对象',(done:any)=>{
const requestInterception:Observable=interceptor.intercept(executionContext,nextCallHander);
requestInterception.subscribe({
下一步:值=>{
// ... ??? ...
},
错误:错误=>{
投掷误差;
},
完成:()=>{
完成();
},
});
});
});
});
我目前不知道下一个回调应该传递什么,但当我尝试按原样运行测试时,它会说requestInterception变量未定义。因此,测试在到达下一个回调之前失败。所以我得到的错误信息是
TypeError:无法读取未定义的属性“subscribe”
我还试着测试响应拦截器,并得出了这个结论
const executionContext: any = {
switchToHttp: jest.fn().mockReturnThis(),
getRequest: jest.fn().mockReturnThis(),
};
const nextCallHander: CallHandler<any> = {
handle: jest.fn(),
};
describe('RequestInterceptor', () => {
let interceptor: RequestInterceptor;
beforeEach(() => {
interceptor = new RequestInterceptor();
});
describe('intercept', () => {
it('should fetch the request object', (done: any) => {
const requestInterception: Observable<any> = interceptor.intercept(executionContext, nextCallHander);
requestInterception.subscribe({
next: value => {
// ... ??? ...
},
error: error => {
throw error;
},
complete: () => {
done();
},
});
});
});
});
const executionContext: any = {
switchToHttp: jest.fn().mockReturnThis(),
getResponse: jest.fn().mockReturnThis()
};
const nextCallHander: CallHandler<any> = {
handle: jest.fn()
};
describe("ResponseInterceptor", () => {
let interceptor: ResponseInterceptor;
beforeEach(() => {
interceptor = new ResponseInterceptor();
});
describe("intercept", () => {
it("should fetch the statuscode and response data", (done: any) => {
const responseInterception: Observable<any> = interceptor.intercept(
executionContext,
nextCallHander
);
responseInterception.subscribe({
next: value => {
// ...
},
error: error => {
throw error;
},
complete: () => {
done();
}
});
});
});
});
const executionContext:any={
switchToHttp:jest.fn().mockReturnThis(),
getResponse:jest.fn().mockReturnThis()
};
const nextCallHander:CallHandler={
句柄:jest.fn()
};
描述(“响应接收器”,()=>{
let拦截器:应答器;
在每个之前(()=>{
侦听器=新的响应侦听器();
});
描述(“截取”,()=>{
它(“应该获取状态码和响应数据”,(完成:任何)=>{
const responseInterception:Observable=拦截器.interception(
执行上下文,
下一个呼叫器
);
responseInterception.subscribe({
下一步:值=>{
// ...
},
错误:错误=>{
投掷误差;
},
完成:()=>{
完成();
}
});
});
});
});
这一次,我在拦截器上遇到了一个错误
TypeError:无法读取未定义的属性“pipe”
能帮我测试一下这两个拦截器吗
提前感谢测试拦截器可能是测试NestJS应用程序最具挑战性的部分之一,因为
ExecutionContext
并从next
返回正确的值
让我们从ExecutionContext
开始:
您已经用当前上下文设置好了,重要的是如果您正在使用HTTP(就像您一样),那么您有一个switchToHttp()
方法,并且switchToHttp()
返回的任何内容都有一个getResponse()
或getRequest()
方法(如果两者都使用)。在那里,getRequest()
或getResponse()
方法应该返回从req和res使用的值,例如res.statusCode
或req.originalUrl
。我喜欢将传入和传出放在同一个拦截器上,因此我的context
对象通常如下所示:
const context={
switchToHttp:jest.fn(()=>({
getRequest:()=>({
原文如下:“/”,
方法:“GET”,
参数:未定义,
查询:未定义,
正文:未定义,
}),
getResponse:()=>({
状态代码:200,
}),
})),
//我最近需要的方法,所以我想我应该添加它
getType:jest.fn(()=>“http”)
}
这只是保持了上下文的轻巧和易于处理。当然,您始终可以根据日志记录的需要,用更复杂的值替换这些值
现在来看有趣的部分,CallHandler
对象。CallHandler
有一个handle()
函数,该函数返回一个可观察的值。至少,这意味着您的下一个对象需要如下所示:
const next={
句柄:()=>共()个
}
但这是非常基本的,对记录响应或处理响应映射没有多大帮助。为了使处理程序功能更健壮,我们可以始终执行以下操作
const next={
handle:jest.fn(()=>of(myDataObject)),
}
现在,如果需要,可以通过Jest重写函数,但一般来说,这就足够了。现在,您的next.handle()
将返回一个可观察值,并将通过RxJS操作符执行pipable操作
现在,为了测试可观察性,您的