记一次SpringBootTest报错AbstractMethodError

记一次SpringBootTest报错AbstractMethodError文章目录注解@SpringBootTest遇到的问题Pleasesetthe’defaultServletName’propertyexplicitly.JavaAbstractMethodError原因分析最终解决办法做开发,大多数的时间是在人云亦云,尤其是在遇到了问题之后——在百度、CSDN上没有方向地搜索。一旦遇到这样的情况,从基础的文档看起,往往屡试不爽。注解@SpringBootTest@SpringBootTest下的属性:property说明cla

大家好,又见面了,我是你们的朋友全栈君。

做开发,大多数的时间是在人云亦云,尤其是在遇到了问题之后——在百度、CSDN上没有方向地搜索。一旦遇到这样的情况,从基础的文档看起,往往屡试不爽。

注解@SpringBootTest

@SpringBootTest下的属性:

property 说明
classes 启动类
webEnvironment 单元测试web环境,取值参考属性详解

Springboot中我们通常这样在Test类上方添加注解:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = VisitCenterApp.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@Slf4j

遇到的问题

Please set the ‘defaultServletName’ property explicitly.

单元测试时load ApplicationContext失败。

java.lang.IllegalStateException: Failed to load ApplicationContext

	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:123)
	at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190)
	at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultServletHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'defaultServletHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: Unable to locate the default servlet for serving static content. Please set the 'defaultServletName' property explicitly.

关键词:Please set the ‘defaultServletName’ property explicitly.
解决办法:
在SwaggerConfig中添加:

@Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 
   
        configurer.enable("visit-center");
    }

添加之后,果然报错信息变了:

Caused by: org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.AbstractMethodError: org.springframework.boot.test.mock.web.SpringBootMockServletContext.getContextPath()Ljava/lang/String;
	at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:185)
	at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53)
	at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360)
	at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158)
	at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:894)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)

相关文档:https://blog.csdn.net/weixin_43114485/article/details/106780813
SpringBoot测试junit遇到的坑

相关称能解决的文档:https://blog.csdn.net/MuErHuoXu/article/details/86750497,但是仍然失败。

最新尝试:看到一个新的注解:@AutoConfigureMockMvc。顺便学习了AutoConfigureMockMvc相关的概念——虽然没能解决我的相关问题。

Spring Boot 2 实战:mock测试你的web应用
spring boot 单元测试使用new MockMvc和@RunWith+@AutoConfigureMockMvc注解的区别

Java AbstractMethodError 原因分析

继续探索:相关内容来自于CSDN。Java AbstractMethodError 原因分析
本文的问题都是来自于一个项目。新猜想:这个项目用到了用到OpenFeign声明一个方法。但是远程调用的方法的声明发生了变化。于是对单元测试造成了影响。

背景

AbstractMethodError异常对于我来说还是比较不常遇见的,最近有幸遇到,并侥幸的解决了,在这里把此种场景剖析一番,进入正题,下面是AbstractMethodError在Java的异常机制中所处的位置:

AbstractMethodError类图

现在明确了AbstractMethodError所具有的特性:

1.它是Error的子类,Error类及其子类都是被划分在非检查异常之列的,就是说这些异常不能在编译阶段被检查出来,只能在运行时才会触发。

2.通过API文档里面的解释大致得出的结论就是说A依赖于B,但是执行的时候发现类B的定义发生了改变,这个改变是针对编译的时候发生了改变,也就是说将类A由java文件编译成.class文件的时候用到了类B的class文件,但是在执行的时候JVM发现真正用到的B的class文件和编译的时候用的不是一个了。于是这个异常就被抛了出来。

至此,AbstractMethodError发生的底层原因也了解的差不多了,再往深层的话就是java的编译机制,以及java代码的执行检查这些更靠近虚拟机的东东,那些我也没什么研究,暂且不表。

底层原因了解了,我们继续谈下平常遇到的更直观的场景:

ClassA ->AbstractClassB ClassA 依赖于AbstractClassB,通常A是我们自己开发的类,而B则是引用的第三方jar包里面的抽象类。我们的项目中又存在AbstractClassB的多个实现版本,比如:1.0,1.2,2.0等版本,通常主版本号发生了改变的话,一般都是不兼容的。

类A

class A { 
   
	B dependency = new BImpl();
	public void testMethod(){ 
   
		dependency.changedMethodInDifVersion(arg1, arg2);
	}
}

1.0版本的AbstractClassB:

abstract class B { 
   
    // v1.0
    public abstract void changedMethodInDifVersion(int arg1);
}
class BImpl extends B{ 
   
    public void changedMethodInDifVersion(int arg1){ 
   
        System.out.prinln("我是AbstractClassB 的 1.0 版本实现,Class A编译的时候我没参与,但是Class A运行的时候我却参与了。");        
    }
}

2.0版本的AbstractClassB:

abstract class B { 
   
    //v2.0
    public abstract void changedMethodInDifVersion(int arg1, String arg2);
}
class BImpl extends B{ 
   
    public void changedMethodInDifVersion(int arg1, String arg2){ 
   
        System.out.prinln("我是AbstractClassB 的 2.0 版本实现,编译的时候是我参与了编译");        
    }
}

如果在编译的时候使用的2.0版本中的BImpl和2.0版本的AbstractClassB,然而执行的时候使用的又是1.0版本的BImpl,那么就会抛出AbstractMethodError,这个异常抛出以后会把运行时真正找到的那个方法签名给打印出来的,异常信息会入下:

Exception in Thread XXXXX java.lang.AbstractMehodError package.Class.运行时实际找到的方法

这个时候在你的classpath中寻找这个类,剔除掉不需要的版本就可以了。

如果在编译的时候使用的2.0版本中的BImpl和2.0版本的AbstractClassB,然而执行的时候使用的又是1.0版本的BImpl 和 1.0版本的AbstractClassB,就会报NoSuchMethodError。

最终解决办法

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-mock</artifactId>
    <version>2.0.8</version>
</dependency>

原来是同事“偷偷”多加了这个jar包,与SpringbootTest产生了jar包冲突,从而导致的单元测试报错。

感谢您的赏读。要不,来个一键三连?点赞、收藏、加关注,
或者留下您的问题让我们一起探讨!一起进步!!

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141705.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql数据库基础知识总结

    mysql数据库基础知识总结mysql数据库基础知识总结一、基础常用命令1.创建命令createuser‘用户名’@‘ip’identifiedby‘密码’;创建用户dropuser用户名@ip删除用户showdatabases;查数据库showtables;看表createdatabase数据库名defaultcharsetutf8;创建数据库createtable表名(列名数据类型约束···,列名数据类型约束···)engine=in

    2022年6月26日
    20
  • GNU make manual 翻译( 一百一十八)

    GNU make manual 翻译( 一百一十八)

    2022年3月12日
    46
  • Spring Data JPA 之 JpaRepository

    Spring Data JPA 之 JpaRepositoryJpaRepository是Spring提供的非常强大的基本接口。1JpaRepository1.1JpaRepository接口定义JpaRepository接口的官方定义如下:publicinterfaceJpaRepository&lt;T,ID&gt;extendsPagingAndSortingRepository&lt;T,ID&gt;,Q…

    2022年10月20日
    0
  • navicat15.0激活码【2021最新】「建议收藏」

    (navicat15.0激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月26日
    458
  • Java异常类型及处理

    Java异常类型及处理前言:Java异常,大家都很熟悉。但是对于具体怎么分类的,JVM对其怎么处理的,代码中怎么处理的,应该怎么使用,底层怎么实现的等等,可能就会有些不是那么清晰。本文基于此详细捋一下异常类型,实现以及使用时应怎么注意。一、异常实现及分类1.先看下异常类的结构图上图可以简单展示一下异常类实现结构图,当然上图不是所有的异常,用户自己也可以自定义异常实现。上图已经足够帮我们解释和理解异常…

    2022年5月19日
    34
  • 儿童计算机编程主要是学什么,儿童编程是什么教什么?学习少儿编程有3大好处…

    少儿编程在中国起步较晚,但政策很好,技术发展也作为一个重要议题提上议事日程,为节目制作行业的发展提供了良好的土壤和坚实的基础,尤其是儿童节目的编排。在2018年,人工智能再次被写入工作报告。同时,我国的大学、中小学也逐步开设了程序设计和人工智能课程。由此可见,我国也在鼓励普及和推广节目教育,使更多的儿童学会编程。少儿编程是学什么的?少儿编程并不是让孩子成为程序员,而是要学会编程思维应用在日常的学习…

    2022年4月14日
    50

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号