Spring Boot 测试应用程序 Yaml java.lang.IllegalStateException:Tomcat 连接器处于失败状态
Posted
技术标签:
【中文标题】Spring Boot 测试应用程序 Yaml java.lang.IllegalStateException:Tomcat 连接器处于失败状态【英文标题】:Spring Boot Testing Application Yaml java.lang.IllegalStateException: Tomcat connector in failed state 【发布时间】:2016-06-28 03:54:21 【问题描述】:我是测试 spring 应用程序的新手,不知道如何测试在我的 spring boot 应用程序中定义的应用程序配置文件 application.yml。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = WebApplication.class)
@WebAppConfiguration
public class ApplicationSettingsTest
@Test
public void applicationPicksRightTeamProfile() throws Exception
WebApplication.main(new String[] "--spring.profiles.active=FalconDev1" );
String output = this.outputCapture.toString();
assertThat(output, containsString("falcondev.io"));
@Test
public void applicationPicksRightDefaultProfile() throws Exception
WebApplication.main(new String[0]);
String output = this.outputCapture.toString();
assertThat(output, containsString("defaultdev.io"));
我的第一个测试似乎通过了,但第二个测试失败并出现多个错误,
org.apache.catalina.LifecycleException: 无法启动组件 [连接器[org.apache.coyote.http11.Http11NioProtocol-8090]]
原因:org.apache.catalina.LifecycleException: service.getName(): “雄猫”;协议处理程序启动失败 org.apache.catalina.connector.Connector.startInternal(Connector.java:1014) ~[tomcat-embed-core-7.0.59.jar:7.0.59]
原因:java.net.BindException:地址已在使用中 sun.nio.ch.Net.bind(本机方法)~[na:1.6.0_65] org.springframework.boot.context.embedded.EmbeddedServletContainerException: 无法在以下位置启动嵌入式 Tomcat servlet 容器 org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.start(TomcatEmbeddedServletContainer.java:165) 原因:java.lang.IllegalStateException:Tomcat 连接器失败 状态在 org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.start(TomcatEmbeddedServletContainer.java:159) ~[spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
编辑: application.yml
server:
port: $port:8090
我确实知道应用程序实际上已在端口 8090 上启动,而我第二次尝试在同一端口上再次运行,这是我不想要的。
那么如何在我的测试中告诉我只是加载应用程序上下文而不是启动真正的应用程序。任何想法都值得赞赏。
【问题讨论】:
WebApplication.main(new String[0])
- 以下代码不会创建 Spring 上下文。你只打电话给java
班级。你测试什么功能?
好吧,我的目的是测试行为,当应用程序没有传递命令行参数时。所以我使用了新的字符串 [0]。在这种情况下,我希望使用默认配置文件。这很好。但问题是当我同时运行两个测试时。
为此使用Environment
。请参阅文档docs.spring.io/spring/docs/current/javadoc-api/org/…。
如果您想在 Spring 初始化应用程序之前设置配置文件,您可以使用以下示例 - github.com/jhipster/generator-jhipster/blob/master/generators/… 和 github.com/jhipster/generator-jhipster/blob/master/generators/…
【参考方案1】:
以下代码将运行带有随机端口的spring boot嵌入式容器:
@IntegrationTest("server.port:0")
为了在测试中设置 Spring 活动配置文件,您可以使用 ActiveProfiles
annotation。
@ActiveProfiles("test")
在应用程序属性中设置spring.profiles.active
,或者使用--spring.profiles.active=test
通过环境变量设置。
Spring 包含 Environment
bean。如果您想在代码中获取配置文件,可以使用以下代码:
@Autowired
Environment environment;
String[] profiles = environment.getActiveProfiles();
以下代码WebApplication.main(new String[0]);
不正确。您确实运行了 2 个 Spring 上下文。
【讨论】:
感谢您的回复。仍然遇到同样的问题。我在测试类中使用您的代码以及我在问题中粘贴的代码。 我认为问题在于两个测试都在同一个端口上运行导致错误。不过,我在获取配置文件时没有问题。 同意你的观点,那么当没有参数通过时,我如何测试我的应用程序是否选择了“默认配置文件”? 注入Environment
和测试值。上面的代码几乎可以满足您的所有需求。
是的,您不必这样做WebApplication.main(new String[0])
。这是不正确的。 @SpringApplicationConfiguration(classes = WebApplication.class)
已经处理好了。【参考方案2】:
听到的问题是,您首先使用指令WebApplication.main(....);
处理 Spring 上下文
听到的关键点是测试类断言你有一个测试上下文,这将是一个用于在这个阶段进行测试的 Spring 上下文你没有为此启动嵌入式 tomcat 我可以建议使用@WebIntegrationTest
没有@WebAppConfiguration
。
在您的情况下,在第一个测试方法中,您将有一个用于测试的 Spring 上下文,然后您开始另一个 Spring 竞赛,该竞赛也将 tomcat 启动到 8090
端口,此后第二个测试方法继承了测试上下文,但在您在同一端口上重新启动上下文和另一个 tomcat 的测试方法,在此阶段您会遇到异常。
@IntegrationTest("server.port:0")
不起作用,因为此注释适用于测试上下文,而不是您开始的上下文。
我的建议是以这种方式重构您的代码:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = WebApplication.class)
@WebIntegrationTest(randomPort = true)
@ActiveProfiles("FalconDev1")
public class ApplicationSettingsTest
@Test
public void applicationPicksRightTeamProfile() throws Exception
String output = this.outputCapture.toString();
assertThat(output, containsString("falcondev.io"));
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = WebApplication.class)
@WebIntegrationTest(randomPort = true)
public class ApplicationSettingsTest
@Test
public void applicationPicksRightDefaultProfile() throws Exception
String output = this.outputCapture.toString();
assertThat(output, containsString("defaultdev.io"));
两个测试类映射您的两个测试集,在第一个中,您可以测试配置文件FalconDev1
,与默认值隔离,在第二个中,您可以测试另一个配置文件。通过这种方式,您可以从 Spring 抽象中受益。
希望对你有帮助
【讨论】:
我试过这个,虽然它看起来是孤立的,但是当我从包中运行两个测试类时我得到了同样的错误。 你试过两个分开的测试类吗?............这很奇怪,因为我没有你的问题,你的错误来源是' t 与测试类相关........我不知道这个方法是否有效,你能提供更多关于配置的细节吗? 是的,当我同时运行这两个类时,应用程序正在同一个端口上启动。 你使用 maven 来运行测试吗?还有更多的是你删除了 WebApplication.main(..) 非常重要,不要忘记 WebIntegrationTestannotation 上的 randomPort = true以上是关于Spring Boot 测试应用程序 Yaml java.lang.IllegalStateException:Tomcat 连接器处于失败状态的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 测试应用程序 Yaml java.lang.IllegalStateException:Tomcat 连接器处于失败状态
Spring Boot 测试使用 Configuration Properties 填充 Map
如果 yaml 文件不是 application.yml,则未正确加载 spring boot 应用程序上下文
如何使用 spring boot + .yaml 创建配置文件?