我在线搜索了很多,我找不到使用自动装配构造函数进行单元测试的示例.我使用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;
}
...
}
最佳答案
我们可以使用jmockito框架来模拟对象.
使用@InjectMocks通过Mockito进行依赖注入
你还有@InjectMocks注释,它试图根据类型进行构造函数,方法或字段依赖注入.以下代码是Javadoc中稍微修改过的示例.
// Mockito can construct this class via constructor
public class ArticleManager {
ArticleManager(ArticleCalculator calculator,ArticleDatabase database) {
}
}
// Mockito can also perform method injection
public class ArticleManager {
ArticleManager() { }
void setDatabase(ArticleDatabase database) { }
void setCalculator(ArticleCalculator calculator) { }
}
// Mockito can also perform field injection
public class ArticleManager {
private ArticleDatabase database;
private ArticleCalculator calculator;
}
以下是单元测试类.
@RunWith(MockitoJUnitRunner.class)
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Spy private UserProvider userProvider = new ConsumerUserProvider();
// creates instance of ArticleManager
// and performs constructor injection on it
@InjectMocks private ArticleManager manager;
@Test public void shouldDoSomething() {
// assume that ArticleManager has a method called initialize which calls a method
// addListener with an instance of ArticleListener
manager.initialize();
// validate that addListener was called
verify(database).addListener(any(ArticleListener.class));
}
}
确保您使用的是@RunWith(MockitoJUnitRunner.class)
有关更多信息,请参阅http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/InjectMocks.html.