使用PowerMock模拟静态类时抛出javax.servlet.http.HttpSession找不到异常怎么办
异常本质
这个报错和你写的静态方法mock逻辑本身无关,是PowerMock在对@PrepareForTest标注的my.pkg.Client类做字节码增强(替换静态方法逻辑的前置操作)时,通过Javassist解析类的方法元数据,发现Client类的createSession方法签名中引用了javax.servlet.http.HttpSession类型,但当前测试运行的类路径中不存在这个类,因此直接抛出类找不到的异常,整个增强流程直接中断。
从异常栈最底层可以看到,触发点是Javassist扫描方法参数类型时,调用ClassPool.get("javax.servlet.http.HttpSession")没找到对应类。PowerMock的类增强流程比普通类加载更严格:哪怕你根本不会调用某个方法,只要类定义里的方法签名引用了不在类路径的类,就会在加载阶段直接报错。
可落地的解决方法
- 补全测试类路径的servlet依赖。既然生产代码中
Client类本身引用了HttpSession类型,说明生产编译环境是存在servlet相关依赖的,只是单元测试运行时没有将这个依赖纳入test作用域。只需要在项目依赖配置中,将javax.servlet:javax.servlet-api的scope设置为test或provided,保证测试运行时类路径能加载到HttpSession类即可,不会对生产打包产生额外影响。 - 跳过PowerMock对缺失类的解析。如果不想额外引入servlet依赖,可以在测试类上增加
@PowerMockIgnore("javax.servlet.*")注解,指定PowerMock在做类增强时,直接跳过javax.servlet包下的所有类,不需要强行加载解析这些外部依赖,从根源上避免类找不到的问题。 - 核对
Client.createSession的真实方法签名。你写的mock语句中第二个、第三个参数用了无类型的any()匹配器,需要确认这个方法的真实入参是不是包含HttpSession类型:如果确实是方法入参包含了这个类型,不管你写不写匹配器,PowerMock在增强类的时候都必须解析完所有方法的参数类型才能完成字节码修改,必然会因为找不到类报错;如果是你误匹配了不存在的重载方法,修正mock语句的参数类型匹配逻辑也能绕开这个问题。
内容的提问来源于stack exchange,提问作者JGleason
相关产品推荐
相关产品推荐

