web-dev-qa-db-ja.com

Springの自動配線コンストラクターをJUnitでテストするにはどうすればよいですか?

私はオンラインでかなりの検索を行いましたが、自動配線されたコンストラクターを使用した単体テストの例を見つけることができません。 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;
    }
    ...
}
8
jencoston

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

6
Sudhakar