首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何测试NestJ响应拦截器

如何测试NestJ响应拦截器
EN

Stack Overflow用户
提问于 2021-09-30 13:27:33
回答 3查看 2.2K关注 0票数 1

我试着跟踪这条线,但它总是出错。

transform-response.interceptor.ts:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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);
    });
  });
});

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-09-30 15:28:48

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

代码语言:javascript
复制
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');
    });
});

我的拦截器正在添加一个标头字段,但是对于您的拦截器,您可以用您的拦截器替换我正在使用的报头拦截器。在那里,您可以测试响应是否包含所需的内容。

票数 0
EN

Stack Overflow用户

发布于 2022-05-02 06:58:56

我将从我的项目中展示一个简单而干净的现实世界示例。该示例类似于问题中所示的示例,该问题涉及使用拦截器转换对象。我使用这个拦截器将像hashedPassword这样的敏感属性从作为response发送的user对象中排除出来。

代码语言:javascript
复制
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-玩笑包的createMock()函数。

NestJS Interceptor在引擎盖下使用RxJS。因此,当框架调用其intercept()方法时,它返回对象的Observable。为了从这个Observable中清晰地提取我们的值,我们从RxJS中使用了方便函数lastValueFrom()

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

票数 2
EN

Stack Overflow用户

发布于 2021-09-30 15:46:13

如果您正在寻找一个简单的单元测试,那么您需要了解RxJS是如何用于异步测试的。类似于以下内容的方法可能会奏效:

代码语言:javascript
复制
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()
    })
  });

});
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69393098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档