SpringBoot Test的webEnvironment源码解读
序
本文主要研究一下SpringBootTest的webEnvironment
SpringBootTest
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@ExtendWith({SpringExtension.class})
public @interface SpringBootTest {
@AliasFor("properties")
String[] value() default {};
@AliasFor("value")
String[] properties() default {};
String[] args() default {};
Class<?>[] classes() default {};
WebEnvironment webEnvironment() default SpringBootTest.WebEnvironment.MOCK;
}SpringBootTest的webEnvironment默认为SpringBootTest.WebEnvironment.MOCK
WebEnvironment
/**
* An enumeration web environment modes.
*/
enum WebEnvironment {
/**
* Creates a {@link WebApplicationContext} with a mock servlet environment if
* servlet APIs are on the classpath, a {@link ReactiveWebApplicationContext} if
* Spring WebFlux is on the classpath or a regular {@link ApplicationContext}
* otherwise.
*/
MOCK(false),
/**
* Creates a web application context (reactive or servlet based) and sets a
* {@code server.port=0} {@link Environment} property (which usually triggers
* listening on a random port). Often used in conjunction with a
* {@link LocalServerPort @LocalServerPort} injected field on the test.
*/
RANDOM_PORT(true),
/**
* Creates a (reactive) web application context without defining any
* {@code server.port=0} {@link Environment} property.
*/
DEFINED_PORT(true),
/**
* Creates an {@link ApplicationContext} and sets
* {@link SpringApplication#setWebApplicationType(WebApplicationType)} to
* {@link WebApplicationType#NONE}.
*/
NONE(false);
private final boolean embedded;
WebEnvironment(boolean embedded) {
this.embedded = embedded;
}
/**
* Return if the environment uses an {@link ServletWebServerApplicationContext}.
* @return if an {@link ServletWebServerApplicationContext} is used.
*/
public boolean isEmbedded() {
return this.embedded;
}
}WebEnvironment有四个枚举,分别是MOCK、RANDOM_PORT、DEFINED_PORT、NONE
SpringBootTestContextBootstrapper
spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java
public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstrapper {
private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private static final String REACTIVE_WEB_ENVIRONMENT_CLASS = "org.springframework."
+ "web.reactive.DispatcherHandler";
private static final String MVC_WEB_ENVIRONMENT_CLASS = "org.springframework.web.servlet.DispatcherServlet";
private static final String JERSEY_WEB_ENVIRONMENT_CLASS = "org.glassfish.jersey.server.ResourceConfig";
private static final String ACTIVATE_SERVLET_LISTENER = "org.springframework.test."
+ "context.web.ServletTestExecutionListener.activateListener";
private static final Log logger = LogFactory.getLog(SpringBootTestContextBootstrapper.class);
@Override
public TestContext buildTestContext() {
TestContext context = super.buildTestContext();
verifyConfiguration(context.getTestClass());
WebEnvironment webEnvironment = getWebEnvironment(context.getTestClass());
if (webEnvironment == WebEnvironment.MOCK && deduceWebApplicationType() == WebApplicationType.SERVLET) {
context.setAttribute(ACTIVATE_SERVLET_LISTENER, true);
}
else if (webEnvironment != null && webEnvironment.isEmbedded()) {
context.setAttribute(ACTIVATE_SERVLET_LISTENER, false);
}
return context;
}
//......
}SpringBootTestContextBootstrapper继承了DefaultTestContextBootstrapper,其buildTestContext方法会判断webEnvironment,然后决定ACTIVATE_SERVLET_LISTENER是设置为true还是false,在为MOCK的时候该值为true
ServletTestExecutionListener
spring-test/src/main/java/org/springframework/test/context/web/ServletTestExecutionListener.java
private boolean isActivated(TestContext testContext) {
return Boolean.TRUE.equals(testContext.getAttribute(ACTIVATE_LISTENER)) || AnnotatedElementUtils.hasAnnotation(testContext.getTestClass(), WebAppConfiguration.class);
}
private void setUpRequestContextIfNecessary(TestContext testContext) {
if (!isActivated(testContext) || alreadyPopulatedRequestContextHolder(testContext)) {
return;
}
ApplicationContext context = testContext.getApplicationContext();
if (context instanceof WebApplicationContext) {
WebApplicationContext wac = (WebApplicationContext) context;
ServletContext servletContext = wac.getServletContext();
Assert.state(servletContext instanceof MockServletContext, () -> String.format(
"The WebApplicationContext for test context %s must be configured with a MockServletContext.",
testContext));
if (logger.isDebugEnabled()) {
logger.debug(String.format(
"Setting up MockHttpServletRequest, MockHttpServletResponse, ServletWebRequest, and RequestContextHolder for test context %s.",
testContext));
}
MockServletContext mockServletContext = (MockServletContext) servletContext;
MockHttpServletRequest request = new MockHttpServletRequest(mockServletContext);
request.setAttribute(CREATED_BY_THE_TESTCONTEXT_FRAMEWORK, Boolean.TRUE);
MockHttpServletResponse response = new MockHttpServletResponse();
ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
RequestContextHolder.setRequestAttributes(servletWebRequest);
testContext.setAttribute(POPULATED_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE);
testContext.setAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE);
if (wac instanceof ConfigurableApplicationContext) {
@SuppressWarnings("resource")
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) wac;
ConfigurableListableBeanFactory bf = configurableApplicationContext.getBeanFactory();
bf.registerResolvableDependency(MockHttpServletResponse.class, response);
bf.registerResolvableDependency(ServletWebRequest.class, servletWebRequest);
}
}
}ServletTestExecutionListener的isActivated会判断ACTIVATE_SERVLET_LISTENER是不是设置为true,或者testClass有标注@WebAppConfiguration; setUpRequestContextIfNecessary方法会调用isActivated来决定是否初始化MockHttpServletRequest等设置
小结
SpringBootTest的webEnvironment默认为SpringBootTest.WebEnvironment.MOCK,它会设置ACTIVATE_SERVLET_LISTENER是设置为true,即在ServletTestExecutionListener的isActivated为true,在setUpRequestContextIfNecessary方法会初始化MockHttpServletRequest、MockHttpServletResponse等。
以上就是SpringBootTest的webEnvironment源码解读的详细内容,更多关于SpringBootTest webEnvironment的资料请关注脚本之家其它相关文章!
相关文章
java批量下载将多个文件(minio中存储)压缩成一个zip包代码示例
在Java应用程序中有时我们需要从多个URL地址下载文件,并将这些文件打包成一个Zip文件进行批量处理或传输,这篇文章主要给大家介绍了关于java批量下载将多个文件(minio中存储)压缩成一个zip包的相关资料,需要的朋友可以参考下2023-11-11
SpringBoot + Vue + ElementUI 实现 el-table 分页功能(详细步骤)
本文详细介绍了使用SpringBoot和Vue.js结合ElementUI实现分页功能的数据表格,从后端分页逻辑到前端展示和状态管理,全面解析如何高效处理大量数据,提升用户体验与系统性能,感兴趣的朋友跟随小编一起看看吧2024-09-09
SecurityUtils.getSubject().getPrincipal()为null的问题
这篇文章主要介绍了SecurityUtils.getSubject().getPrincipal()为null的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-07-07
SpringBoot集成redis与session实现分布式单点登录
这篇文章主要介绍了SpringBoot集成redis与session实现分布式单点登录,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下2022-09-09


最新评论