You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest mock未返回rejected Promise反而进入原函数逻辑报错排查

问题根因

mock未生效,核心原因如下:

  • 你在测试文件中声明的generateReportUseCase mock实例,未绑定到Inversify容器,控制器初始化时从ReportServiceLocator获取到的是真实use case实例,不是你创建的mock对象,因此你设置的mockRejectedValue完全不生效,代码直接执行真实use case逻辑。
  • 真实use case运行时,内部依赖的tradeReadOnlyRepository未初始化,this.tradeReadOnlyRepository.fetch()返回undefined,后续调用.then()就会抛出TypeError: Cannot read properties of undefined (reading 'then')报错。

额外代码bug:控制器中读取报表类型参数时写的是req.query.reportformat,但请求传入的参数名是report_type,会导致拿到的report_type值为undefined。

修复方案

1. 正确绑定mock实例到容器

必须将mock的use case实例注册到Inversify容器,替换真实实现,保证控制器依赖注入时拿到的是mock对象,调整测试代码如下:

const container = new Container();

describe('Controller Error Tests', () => {
     let reportController: ReportController;
     let generateReportUseCase: IGenerateReportUseCase;
     // 替换为你项目中绑定IGenerateReportUseCase实际使用的标识符
     const GENERATE_REPORT_USE_CASE_TYPE = Symbol.for("IGenerateReportUseCase");

     beforeAll(async () => {
        cleanUpMetadata();
        dotenv.config();
        // 初始化mock实例并绑定到容器
        generateReportUseCase = mock<IGenerateReportUseCase>();
        container.bind<IGenerateReportUseCase>(GENERATE_REPORT_USE_CASE_TYPE).toConstantValue(generateReportUseCase);
        container.bind<ReportServiceLocator>(TYPES.ReportServiceLocator).to(ReportServiceLocator);
        
        reportController = new ReportController(container.get<ReportServiceLocator>(Symbol.for("ReportServiceLocator")));
    });

    // 每个用例执行前重置mock状态,避免跨用例污染
    beforeEach(() => {
        jest.clearAllMocks();
    })

     it('User held shares report use case throws error', async () => {
        const requestObj = httpMocks.createRequest({
            cookies: {
                token: jwt.sign({ id: 'test' }, process.env.JWT_SECRET_KEY!),
            },
            query: {
                report_type: 'CSV'
            }
        });

        const responseObj = httpMocks.createResponse();
        // 对容器中注入的mock实例设置拒绝返回值
        mock(generateReportUseCase).usersHeldShares.mockRejectedValue(new Error('Could not generate report'));

        await reportController.userHeldShares(requestObj, responseObj);
        expect(responseObj.statusCode).toEqual(500);
    })
})

注意:请将代码中GENERATE_REPORT_USE_CASE_TYPE的值替换为你项目ReportServiceLocator获取IGenerateReportUseCase时实际使用的绑定标识符,确保locator能拿到你注册的mock实例。

2. 修复控制器参数笔误

将控制器中读取报表类型的参数名改为和请求传参一致:

@httpGet('/held-shares')
public async userHeldShares(@request() req: express.Request, @response() res: express.Response){
    const jwtSecretKey = process.env.JWT_SECRET_KEY;
    const ascending: boolean = req.query.ascending === "false" ? false : true;
    // 修正参数名,和请求传入的report_type对应
    const report_type: string = String(req.query.report_type);
    const cookieData = await <IUserDto>jwt.verify(req.cookies.token, jwtSecretKey!);
        
    if(!cookieData.id){
        return res.status(401).json({error: 'User not authorised'});
    }
    
    return await this.generateReportUseCase.usersHeldShares(cookieData.id!, ascending, report_type)
        .then((userDto: IUserDto) => {
            res.status(200).json(userDto)
        })
        .catch((err: Error) => {
            res.status(500).json(err);
        });
}
效果验证

修复后,控制器调用this.generateReportUseCase.usersHeldShares时会直接触发mock方法返回rejected状态的Promise,不会进入真实use case的执行逻辑,异常会被后续的.catch()分支捕获,最终响应状态码正确返回500,符合预期。


内容的提问来源于stack exchange,提问作者Adam Cole

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 06:01:43