2011-09-01 6 views
5

私のコードベースのクラスの1つに、私の人生の間、私のjunitテストには参加できないメソッドがあります。私は、データベース接続を要求する場合、基本的に、このクラスは古い接続が返された場合、新しい接続がここJava - コードカバレッジ

を確立している、と呼ばれ は、私のクラスでmthodの抜粋である(この目的のためにトリムダウン)

public class TCSOracleDataSourceWrapper extends OracleDataSource { 

private static final int STALE_CONNECTION_EX_CODE = 17143; 
private OracleConnectionCacheManager cacheManager; 
private String cacheName; 
/** Local log variable **/ 
private final Log logger = LogFactory.getLog(getClass()); 


/** 
* Class constructor 
* @throws SQLException 
*/ 
public TCSOracleDataSourceWrapper() throws SQLException { 
    super(); 
} 

private static final long serialVersionUID = 1L; 

@Override 
/** 
* Get a connection but if the connection is stale then refresh all DB connections 
* 
*/ 
public final Connection getConnection() throws SQLException { 

    logger.debug("Retrieving a database connection from the pool"); 

    Connection connection = null; 
    try{ 
     connection = super.getConnection();   
    } 
    catch(SQLException e) 
    { 

     if(e.getErrorCode() == STALE_CONNECTION_EX_CODE) 
     {    
      logger.error("Stale Oracle connection found in the Connection Pool. Refreshing invalid DB connections."); 
      //refresh invalid connections 
      cacheManager.refreshCache(cacheName, OracleConnectionCacheManager.REFRESH_INVALID_CONNECTIONS); 
      //now try to get the connection again 
      connection = super.getConnection(); 
     } 
     else 
     { 
      throw e; 
     } 
    }  

    return connection; 
}} 

私のjunitテストがifステートメントを確実に実行できるようにするにはどうすればよいですか? 私は現在、EasyMockとPowermockを使用していますが、なステートメント場合、私はすべてのヘルプが大幅

ありがとう ダミアン

答えて

8

を高く評価しているこれらのツールに

を使用してあなたがあなたのクラスをリファクタリングする必要があり、このに取得する方法を見つけることができません1つを継承するのではなく、別のデータソースのproxyになります。このようにして、実際のデータソースではなく模擬データソースを簡単に注入することができます。

import javax.sql.DataSource; 

public class TCSOracleDataSourceWrapper implements DataSource { 
    ... 
    private DataSource wrappedDataSource; 
    ... 

    public TCSOracleDataSourceWrapper(DataSource ds) { 
    wrappedDataSource = ds; 
    } 

    ... 

    public final Connection getConnection() throws SQLException { 
    ... 

    Connection connection = null; 
    try{ 
     connection = ds.getConnection();   
    } 
    catch(SQLException e) 
    { 
     ... 
    }  

    return connection; 
    } 
} 
3

1つのアイデアが思い浮かぶ:継承ではなく集約を使用する。この問題とそれに類するものは、集約されたオブジェクトをモックして、必要な振る舞いを持つことができるため、消えてしまいます。私はそこに手を差し伸べる別の方法は見当たりません。実際、TCSOracleDataSourceWrapperという名前は、実際にはそうでないときに、データソース(集約)をラップしていることを既に示しています。

1

一時的な回避策として、super.getConnection()呼び出しを新しいプライベート/保護されたメソッドに分解する方法があります。その変更を行うと、power mockを使用してgetBaseConnectionメソッドをモックするのは簡単です。これは短期的な修正です。他の答えと同様に、ラッパー実装の継承の代わりに委譲を使用する方がよいことが示唆されています。

Connection getBaseConnection() throws SQLException { 
    return super.getConnection(); 
} 

public final Connection getConnection() throws SQLException { 

    logger.debug("Retrieving a database connection from the pool"); 

    Connection connection = null; 
    try{ 
     connection = getBaseConnection();   
    } 
    catch(SQLException e) 
    { 

     if(e.getErrorCode() == STALE_CONNECTION_EX_CODE) 
     {    
      logger.error("Stale Oracle connection found in the Connection Pool. Refreshing invalid DB connections."); 
      //refresh invalid connections 
      cacheManager.refreshCache(cacheName, OracleConnectionCacheManager.REFRESH_INVALID_CONNECTIONS); 
      //now try to get the connection again 
      connection = getBaseConnection(); 
     } 
     else 
     { 
      throw e; 
     } 
    }  
    return connection; 
} 
関連する問題