中间件从微服务端点获取JSON文档并将其附加到请求。
好的路径测试是可以的,但是我不能让坏的路径测试抛出ForbiddenException并阻止它调用next()。
在Jest测试之外,如果中间件无法获取json文档,则会阻止请求。
任何帮助是赞赏:)
中间件:
import { ForbiddenException, Injectable, NestMiddleware } from '@nestjs/common'
import { HttpService } from '@nestjs/axios'
import { NextFunction, Request, Response } from 'express'
import { catchError, firstValueFrom } from 'rxjs'
import { LoggerService } from '../logger.service'
@Injectable()
export class MyMiddleware implements NestMiddleware {
constructor(
private logger: LoggerService,
private httpService: HttpService,
) {}
async use(req: Request, res: Response, next: NextFunction) {
const response = await firstValueFrom(
this.httpService
.get('https://myservice/document-endpoint', {
headers: {
Cookie: req.headers['cookie'],
},
})
.pipe(
catchError((error: Error) => {
this.logger.error(error.message);
throw new ForbiddenException()
}),
),
)
req.document = response.data.value
next()
}
}
测试:
“坏路径”测试是问题所在... nextFunction方法被调用,我无法设法让它抛出错误。
import { MyMiddleware } from './mymiddleware'
import { NextFunction, Request, Response } from 'express'
import { LoggerService } from '../logger/logger.service'
import { of } from 'rxjs'
import { createMock } from '@golevelup/nestjs-testing'
import { HttpService } from '@nestjs/axios'
import { AxiosResponse } from 'axios'
describe('Authorization middleware', () => {
let middleware: MyMiddleware
let mockRequest: Partial<Request>
let mockResponse: Partial<Response>
let nextFunction: NextFunction = jest.fn()
let mockHttpService = createMock<HttpService>()
mockRequest = {
headers: {
cookie: 'idToken=asdasdasd'
}
beforeEach(async () => {
mockResponse = {
json: jest.fn(),
}
middleware = new MyMiddleware(new LoggerService(), mockHttpService)
})
test('bad path', async () => {
jest.clearAllMocks()
const mockDocumentResponse: AxiosResponse = {
status: 404,
statusText: '',
headers: {},
config: {},
data: { error: 'Not Found' }
}
const httpSpy = jest.spyOn(mockHttpService, 'get')
.mockReturnValue(of(mockDocumentResponse))
await middleware.use(mockRequest as Request, mockResponse as Response, nextFunction)
expect(nextFunction).toBeCalledTimes(0)
})
test('good path', async () => {
jest.clearAllMocks()
const mockDocumentResponse: AxiosResponse = {
status: 200,
statusText: '',
headers: {},
config: {},
data: {
value: 'example document',
}
}
jest.spyOn(mockHttpService, 'get').mockImplementationOnce(() => of(mockDocumentResponse));
await middleware.use(mockRequest as Request, mockResponse as Response, nextFunction)
expect(nextFunction).toBeCalledTimes(1)
})
})
1条答案
按热度按时间xe55xuns1#
我从来没有抽出时间来发布解决方案,但似乎这个问题得到了一些访问,所以在这里。
关键点是NestJS集成了RxJS作为一等公民,并接受了Observables的概念。HttpService(axios的 Package 器)默认返回Observables。
Observable与promise(https://rxjs.dev/guide/observable)不同,在中间件代码中,这是通过使用firstValueFrom方法(从RxJS导入)来处理的,该方法将Observable转换为常规的JavaScript promise。
因此,当测试“坏路径”时,我们正在使用Observables模拟错误。这可以通过返回一个新的Observable来完成,该Observable使用s.error(err)方法立即抛出错误。