私はオンラインでかなりの検索を行いましたが、自動配線されたコンストラクターを使用した単体テストの例を見つけることができません。 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フレームワークを使用してオブジェクトをモックできます。
Mockitoを介した依存性注入に@InjectMocksを使用する@ 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 。