Spring GenericWebApplicationContext 被加载,尽管 web 应用程序类型:NONE
Spring GenericWebApplicationContext gets loaded despite web-application-type: NONE
在我的 Spring 2.5 web 应用程序中,我试图编写一个测试,在其中禁用它是一个 web 应用程序这一事实:这是因为该应用程序还包含一些使用的计划任务一些 Oauth2 组件调用其他服务。
这些 Oauth2 组件的行为有所不同,具体取决于它们是否从 Servlet 上下文中触发(参见 official doc)。
现在,当我执行 @SpringBootTest
时,我看到了:
[org.springframework.context.support.AbstractApplicationContext] [main] [629] [DEBUG] Refreshing org.springframework.web.context.support.GenericWebApplicationContext
我想禁用它,所以在我的 application.yml 中,我设置了 spring.main.web-application-type=NONE
,但它不起作用我仍然看到 WebApplicationContext(我还设置了 属性到一个错误的值,以确保它被考虑在内并且失败了:它是,所以我知道我的 applicaion.yml 文件被读取并被我测试考虑了)。
我希望一旦我能够禁用它,那么 ServletTestExecutionListener
不会被触发,也不会创建 MockServletContext
。
@SpringBootTest
使用 WebEnvironment.MOCK
作为 webEnvironment
.
的默认配置值
如果您不想针对 WebApplicationContext
进行测试,您可以覆盖此值:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
因为我们无法轻松启用我们需要的自动配置,当我们设置 webEnvironment = SpringBootTest.WebEnvironment.NONE 时被禁用(参见 中的评论),我们必须采取不同的方法。
我们不能轻易阻止 ServletTestExecutionListener
被调用,但我们可以添加我们自己的 TestExecutionListener,它将在测试上下文中重置我们需要的部分。幸运的是,我们添加的侦听器在 ServletTestExecutionListener
之后被调用,因此确实可以“撤消”我们需要的东西。
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import org.springframework.web.context.request.RequestContextHolder;
/**
* It's difficult to test a scheduled task that is part of a web application : out of the box, Spring Boot will set up a mock servlet context
* through {@link org.springframework.test.context.web.ServletTestExecutionListener}. But in production, the servlet context is null and HTTP calls through {@code WebClient} may fail
* if it's not configured correctly - see <a href="https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManager.html">the doc</a>
* for an example of how it should typically configured.
* If not configured correctly, WebClient calls may fail at runtime, and we may not be able to reproduce easily in a test, because servletRequest is no tnull like in prod, but set to a mock servlet context.
*
* Using {@code ResettingServletContextToNullListener}, we reset to null the servletContext that was initialized in {@link org.springframework.test.context.web.ServletTestExecutionListener}, and create a context that is much closer to what it is at runtime in production
*/
public class ResettingServletContextToNullListener extends AbstractTestExecutionListener {
@Override
public void beforeTestMethod(TestContext testContext) {
System.out.println("resetting servletContext to null, like it is at runtime when a scheduled task is triggered..");
RequestContextHolder.setRequestAttributes(null);
}
}
然后我们可以简单地在我们的测试中添加这个:
@SpringBootTest
@TestExecutionListeners(value = ResettingServletContextToNullListener.class, mergeMode = MergeMode.MERGE_WITH_DEFAULTS)
class MyScheduledTaskIntegrationTest {
...
}
使用该设置,计划任务的测试上下文类似于它在生产环境中运行时的情况,即 servletRequest 为空:然后我们可以调整我们的 Oauth2 配置,以便它在运行时不会失败案例.
在我的 Spring 2.5 web 应用程序中,我试图编写一个测试,在其中禁用它是一个 web 应用程序这一事实:这是因为该应用程序还包含一些使用的计划任务一些 Oauth2 组件调用其他服务。
这些 Oauth2 组件的行为有所不同,具体取决于它们是否从 Servlet 上下文中触发(参见 official doc)。
现在,当我执行 @SpringBootTest
时,我看到了:
[org.springframework.context.support.AbstractApplicationContext] [main] [629] [DEBUG] Refreshing org.springframework.web.context.support.GenericWebApplicationContext
我想禁用它,所以在我的 application.yml 中,我设置了 spring.main.web-application-type=NONE
,但它不起作用我仍然看到 WebApplicationContext(我还设置了 属性到一个错误的值,以确保它被考虑在内并且失败了:它是,所以我知道我的 applicaion.yml 文件被读取并被我测试考虑了)。
我希望一旦我能够禁用它,那么 ServletTestExecutionListener
不会被触发,也不会创建 MockServletContext
。
@SpringBootTest
使用 WebEnvironment.MOCK
作为 webEnvironment
.
如果您不想针对 WebApplicationContext
进行测试,您可以覆盖此值:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
因为我们无法轻松启用我们需要的自动配置,当我们设置 webEnvironment = SpringBootTest.WebEnvironment.NONE 时被禁用(参见
我们不能轻易阻止 ServletTestExecutionListener
被调用,但我们可以添加我们自己的 TestExecutionListener,它将在测试上下文中重置我们需要的部分。幸运的是,我们添加的侦听器在 ServletTestExecutionListener
之后被调用,因此确实可以“撤消”我们需要的东西。
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import org.springframework.web.context.request.RequestContextHolder;
/**
* It's difficult to test a scheduled task that is part of a web application : out of the box, Spring Boot will set up a mock servlet context
* through {@link org.springframework.test.context.web.ServletTestExecutionListener}. But in production, the servlet context is null and HTTP calls through {@code WebClient} may fail
* if it's not configured correctly - see <a href="https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/oauth2/client/AuthorizedClientServiceOAuth2AuthorizedClientManager.html">the doc</a>
* for an example of how it should typically configured.
* If not configured correctly, WebClient calls may fail at runtime, and we may not be able to reproduce easily in a test, because servletRequest is no tnull like in prod, but set to a mock servlet context.
*
* Using {@code ResettingServletContextToNullListener}, we reset to null the servletContext that was initialized in {@link org.springframework.test.context.web.ServletTestExecutionListener}, and create a context that is much closer to what it is at runtime in production
*/
public class ResettingServletContextToNullListener extends AbstractTestExecutionListener {
@Override
public void beforeTestMethod(TestContext testContext) {
System.out.println("resetting servletContext to null, like it is at runtime when a scheduled task is triggered..");
RequestContextHolder.setRequestAttributes(null);
}
}
然后我们可以简单地在我们的测试中添加这个:
@SpringBootTest
@TestExecutionListeners(value = ResettingServletContextToNullListener.class, mergeMode = MergeMode.MERGE_WITH_DEFAULTS)
class MyScheduledTaskIntegrationTest {
...
}
使用该设置,计划任务的测试上下文类似于它在生产环境中运行时的情况,即 servletRequest 为空:然后我们可以调整我们的 Oauth2 配置,以便它在运行时不会失败案例.