摘要:将@ComponentScan
(或@SpringBootApplication
)注释添加到我的应用程序类会更改SpringApplicationBuilder.properties()
的行为并中断我的集成测试。
我正在使用Spring Boot示例的简化版本:
spring-boot-sample-websocket-jetty
我删除了除“echo”示例所需的所有内容(我使用的是Spring Boot 1.3.3)。
我留下了以下SampleJettyWebSocketsApplication
代码:
@Configuration
@EnableAutoConfiguration
//@ComponentScan // --- If I uncomment this the test breaks ---
@EnableWebSocket
public class SampleJettyWebSocketsApplication
implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(echoWebSocketHandler(), "/echo").withSockJS();
}
@Bean
public EchoService echoService() {
return new DefaultEchoService("Did you say \"%s\"?");
}
@Bean
public WebSocketHandler echoWebSocketHandler() {
return new EchoWebSocketHandler(echoService());
}
public static void main(String[] args) {
SpringApplication.run(SampleJettyWebSocketsApplication.class, args);
}
}
以下测试类(直接来自Spring Boot示例的代码):
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(SampleJettyWebSocketsApplication.class)
@WebIntegrationTest({"server.port=0"})
@DirtiesContext
public class SampleWebSocketsApplicationTests {
private static Log logger = LogFactory.getLog(SampleWebSocketsApplicationTests.class);
@Value("${local.server.port}")
private int port = 1234;
@Test
public void echoEndpoint() throws Exception {
logger.info("Running the echoEndpoint test. Port: " + port + ". Path: /echo/websocket");
ConfigurableApplicationContext context = new SpringApplicationBuilder(
ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class)
.properties("websocket.uri:ws://localhost:" + this.port
+ "/echo/websocket")
.run("--spring.main.web_environment=false");
long count = context.getBean(ClientConfiguration.class).latch.getCount();
AtomicReference<String> messagePayloadReference = context
.getBean(ClientConfiguration.class).messagePayload;
context.close();
assertThat(count).isEqualTo(0);
assertThat(messagePayloadReference.get())
.isEqualTo("Did you say \"Hello world!\"?");
}
@Configuration
static class ClientConfiguration implements CommandLineRunner {
@Value("${websocket.uri}")
private String webSocketUri;
private final CountDownLatch latch = new CountDownLatch(1);
private final AtomicReference<String> messagePayload = new AtomicReference<String>();
@Override
public void run(String... args) throws Exception {
logger.info("Waiting for response: latch=" + this.latch.getCount());
if (this.latch.await(10, TimeUnit.SECONDS)) {
logger.info("Got response: " + this.messagePayload.get());
}
else {
logger.info("Response not received: latch=" + this.latch.getCount());
}
}
@Bean
public WebSocketConnectionManager wsConnectionManager() {
logger.info("Setting up SimpleClientWebSocketHandler...");
WebSocketConnectionManager manager = new WebSocketConnectionManager(client(),
handler(), this.webSocketUri);
manager.setAutoStartup(true);
return manager;
}
@Bean
public StandardWebSocketClient client() {
return new StandardWebSocketClient();
}
@Bean
public SimpleClientWebSocketHandler handler() {
logger.info("Creating new SimpleClientWebSocketHandler using SimpleGreetingService...");
return new SimpleClientWebSocketHandler(greetingService(), this.latch,
this.messagePayload);
}
@Bean
public GreetingService greetingService() {
return new SimpleGreetingService();
}
}
}
如上所述运行应用程序和单元测试一切正常但是如果我取消注释应用程序类上的@ComponentScan
注释,应用程序仍然运行正常但测试中断错误:
Could not resolve placeholder 'websocket.uri' in string value "${websocket.uri}"
。
我已在setting-the-run-time-properties-on-springapplicationbuilder读到:
您在SpringApplicationBuilder上配置的属性在应用程序的环境中可用,而不是作为系统属性。
在@ComponentScan
javadoc中:
如果未定义特定包,则将从声明此批注的类的包中进行扫描。
但我不明白为什么在添加@ComponentScan
注释时行为会发生变化。
当应用程序类使用websocket.uri
(或@ComponentScan
)进行注释时,如何在测试中设置 System 属性@SpringBootApplication
?
(我的目标是使用@SpringBootApplication
,其中包含@ComponentScan
,但在我开始工作之前我无法做到。)
答案 0 :(得分:0)
添加我的想法(从我可以从你的代码收集的任何东西):
- 尝试在应用程序属性中添加属性websocket.uri,或者如果您的项目包含src / test / resources / test.properties,然后将其添加到test.properties文件中。@ ComponentScan应该选择它。
-Else,你可以说:
public static void main(String[] args) {
System.setProperty("websocket.uri","<your uri>");
SpringApplication.run(SampleJettyWebSocketsApplication.class, args);
}
希望它有所帮助。
答案 1 :(得分:0)
有几种方法可以添加系统属性。
解决方案1:
以if($state.current.name != 'app.details'){
$state.go('app.details.overview');
}
的格式添加Test
的参数,这会将属性-Dabc=xyz
添加到系统属性。
解决方案2: 就像0楼一样。
解决方案3:
只需让abc
加载属性,例如spring-boot
,就可以在其中指定任何属性。
注释classpath:bootstrap.yml
将启用基于当前包或@ComponentScan
的自动扫描。这意味着ComponentScan#basePackages
将被扫描,因为它们具有相同的基础包SampleWebSocketsApplicationTests.ClientConfiguration
。
但是,samples.websocket.jetty
不应解析SampleWebSocketsApplicationTests.ClientConfiguration
因为我们需要手动在SpringJUnit4ClassRunner
中解析它。它只能由SampleWebSocketsApplicationTests#echoEndpoint
中创建的ApplicationContext
解析。
还有,echoEndpoint()
等于同时使用@SpringBootApplication
和@Configuration
以及@EnableAutoConfiguration
,因此请注释@ComponentScan
或{{1}会有同样的效果。
我的建议是将课程@ComponentScan
移至包@SpringBootApplication
(与SampleWebSocketsApplicationTests
不同)并在samples.websocket.jettytest
启用samples.websocket.jetty
或@ComponentScan
并尝试再次。它应该工作。