【发布时间】:2016-10-10 04:28:14
【问题描述】:
我在网上进行了大量搜索,但找不到使用自动装配构造函数进行单元测试的示例。我正在使用 Spring 将属性文件中的值自动装配到我的应用程序中。我想对 MyApp.java 的 start 方法进行单元测试,但我有一个自动装配的构造函数,所以我不知道如何实例化 MyApp。没有自动装配的属性,我在单元测试中这样做:
@Test
public void testStart() {
try{
MyApp myApp = new MyApp();
myApp.start();
}
catch (Exception e){
fail("Error thrown")
}
}
我不想模拟自动装配,因为我需要从属性文件中获取值并使事情进一步复杂化,我通过注释来配置所有内容。我没有 spring.xml、application-context.xml 或 web.xml 文件。那么我该如何实例化/测试 MyApp 的 start 方法呢?我尝试添加 @RunWith(SpringJUnit4ClassRunner.class) 并自动装配 MyApp myApp,但它会引发有关无法加载应用程序上下文的错误,这些错误无法通过在测试类上实现 ApplicationContextAware 来修复。
这里是 MyApp.java
@Component
public class MyApp {
private static ApplicationContext applicationContext;
private static MyAppProperties myAppProperties;
//Obtain the values from the app.properties file
@Autowired
MyApp(MyAppProperties myAppProps){
myAppProperties = myAppProps;
}
public static void main(String[] args) throws Exception {
// Instantiate the application context for use by the other classes
applicationContext = new AnnotationConfigApplicationContext("com.my.company");
start();
}
/**
* Start the Jetty server and configure the servlets
*
* @throws Exception
*/
public static void start() throws Exception {
// Create Embedded Jetty server
jettyServer = new Server();
// Configure Jetty so that it stops at JVM shutdown phase
jettyServer.setStopAtShutdown(true);
jettyServer.setStopTimeout(7_000);
// Create a list to hold all of the handlers
final HandlerList handlerList = new HandlerList();
// Configure for Http
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(myAppProperties.getHTTP_SECURE_PORT());
....
}
}
这是我的 app.properties 文件
# Spring Configuration for My application
#properties for the embedded jetty server
http_server_port=12345
这里是 MyAppProperties.java
@Component
public class MyAppProperties implements ApplicationContextAware {
private ApplicationContext applicationContext;
//List of values from the properties files to be autowired
private int HTTP_SERVER_PORT;
...
@Autowired
public MyAppProperties( @Value("${http_server_port}") int http_server_port, ...){
this.HTTP_SERVER_PORT = http_server_port;
}
/**
* @return the applicationContext
*/
public ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* @param applicationContext
* the applicationContext to set
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
/**
* @param name
* the name to set
*/
public void setHTTP_SERVER_PORT(String name) {
JETTY_SERVER_NAME = name;
}
/**
* @return the httpServerPort
*/
public int getHTTP_SERVER_PORT() {
return HTTP_SERVER_PORT;
}
}
这里是 MyAppTest.java
@RunWith(SpringJUnit4ClassRunner.class)
public class MyAppTest implements ApplicationContextAware{
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext appContext) {
applicationContext = appContext;
}
@Autowired
private MyApp myapp;
@Test
public void testStart(){
try {
if(myapp != null){
myapp.start();
}
else{
fail("myapp is null");
}
} catch (Exception e) {
fail("Error thrown");
e.printStackTrace();
}
}
}
更新:这是我的配置类
@Configuration
@Component
public class ApplicationConfig implements ApplicationContextAware {
private final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class);
private ApplicationContext applicationContext;
/**
* @return the applicationContext
*/
public ApplicationContext getApplicationContext() {
LOGGER.debug("Getting Application Context", applicationContext);
return applicationContext;
}
/**
* @param applicationContext
* the applicationContext to set
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
// Needed for @Value
/**
* Property sources placeholder configurer.
*
* @return the property sources placeholder configurer
*/
@Bean
public PropertyPlaceholderConfigurer getPropertyPlaceholderConfigurer() {
PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer();
propertyPlaceholderConfigurer.setLocation(new ClassPathResource("app.properties"));
return propertyPlaceholderConfigurer;
}
...
}
【问题讨论】:
-
只添加
@RunWith并且不告诉加载哪个配置会失败。你必须在你的测试类中添加一个public static class,把@Configuration和@ComponentScan("your.package")放在上面。在另一个层面上,我建议使用 Spring Boot 来引导您的应用程序并注入/使用属性,因为您似乎正在做 Spring Boot 提供的开箱即用(包括对其的测试支持)。 -
@M.Deinum 不幸的是,由于与其他工具的冲突,我无法选择 Spring Boot。只是为了澄清你是说我应该将我的测试类更改为公共静态类 MyAppTest 还是我应该制作另一个类?当我尝试将 MyAppTest 类设为静态时,我收到一条错误消息,指出它是非法修饰符。
-
不,你需要添加一个内部配置类。此外,我看不出 Spring Boot 对内部服务器的操作与您自己的操作有什么不同,实际上应该没有任何区别。
-
@M.Deinum 我已经有配置类,抱歉我忘了包含它。我已经编辑了问题以添加它。你能解释一下“笑内部服务器”是什么意思吗?我以前从未听过这句话。
-
这是自动更正的。我的意思当然是发射而不是笑。
标签: spring unit-testing junit