package jp.terasoluna.fw.batch.unit.testcase.junit4; import org.junit.After; import org.junit.Before; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import org.springframework.test.context.transaction.AfterTransaction; import org.springframework.test.context.transaction.BeforeTransaction; import org.springframework.test.context.transaction.TransactionalTestExecutionListener; import org.springframework.util.Assert; import jp.terasoluna.fw.batch.unit.testcase.TestCaseUtils; import jp.terasoluna.fw.batch.unit.testcase.junit4.listener.DaoTestCaseExecutionListener; import jp.terasoluna.fw.batch.unit.testcase.junit4.loader.DaoTestCaseContextLoader; import jp.terasoluna.fw.batch.unit.util.JdbcTemplateUtils; /** * JUnit4用DAO実行試験支援テストケース。 * * <pre> * 本試験では前処理中にSpringの{@link org.springframework.context.ApplicationContext}を作成します。 * 作成時には次の設定ファイルを読み込みます。 * </pre> * <table border=1> * <tr> * <th>設定ファイル</th> * <th>デフォルト値</th> * <th>変更ポイント</th> * <th>備考</th> * </tr> * <td>共通Bean定義ファイル</td> * <td>WebContext/WEB-INF/applicationContext.xml</td> * <td>テストクラスに <code>@{@link ContextConfiguration}</code>アノテーションを付与し、その<code>loader</code>プロパティに{@link DaoTestCaseContextLoader}<code>.class</code>を設定してください。<br> * (<strong style="color:red">{@link DaoTestCase}では明示的な設定は不要でしたが、JUnit4用では明示的に設定する必要があります</strong>) <br> * ※例<br> * * <pre> * {@literal @}ContextConfiguration(locations = { ... }, loader = <strong style="color:red">DaoTestCaseContextLoader.class</strong>) * public class SampleBLogic1Test extends DaoTestCaseJunit4 { * </pre> * * <hr> * <br> * terasoluna-unit-override.propertiesの以下にキーに対する値を設定することで、変更可能です。<br> * WebContext → webapp.pathキー<br> * WEB-INF → webinf.dirキー<br> * applicationContext.xml → applicationcontext.fileキー<br></td> * <td>ファイルが存在しない場合、無視します。</td> * </tr> * <tr> * <td>モジュールBean定義ファイル</td> * <td>WebContext/WEB-INF/moduleContext.xml</td> * <td>テストクラスに <code>@{@link ContextConfiguration}</code>アノテーションを付与し、その<code>loader</code>プロパティに{@link DaoTestCaseContextLoader}<code>.class</code>を設定してください。<br> * (<strong style="color:red">{@link DaoTestCase}では明示的な設定は不要でしたが、JUnit4用では明示的に設定する必要があります</strong>) <br> * ※例<br> * * <pre> * {@literal @}ContextConfiguration(locations = { ... }, loader = <strong style="color:red">DaoTestCaseContextLoader.class</strong>) * public class SampleBLogic1Test extends DaoTestCaseJunit4 { * </pre> * * <hr> * <br> * terasoluna-unit-override.propertiesの以下にキーに対する値を設定することで、変更可能です。<br> * WebContext → webapp.pathキー<br> * WEB-INF → webinf.dirキー<br> * moduleContext.xml → modulecontext.fileキー<br></td> * <td>ファイルが存在しない場合、無視します。コンストラクタにて{@link #setLoadDefaultConfig(boolean)} でfalseを設定した場合または{@link #isLoadDefaultConfig()}がfalseを返すようにオーバライドした場合、読み込みません。</td> * </tr> * <tr> * <td>試験毎Bean定義ファイル</td> * <td>なし</td> * <td> * テストクラスに <code>@{@link ContextConfiguration}</code>アノテーションを付与し、その<code>locations</code>プロパティに読み込ませるパスを指定してください(複数可)。<br> * ※例<br> * * <pre> * {@literal @}ContextConfiguration(<strong style="color:red">locations = { "classpath:sampleBLogic1.xml", ... }</strong>) * public class SampleBLogic1Test extends DaoTestCaseJunit4 { * </pre> * * </td> * <td> </td> * </tr> * </table> * * <pre> * Bean定義ファイル中には{@link java.sql.DataSource}の定義が必要であり、DBを接続した試験を行うことができます。 * (ただし、DB環境を用意する必要があります。) * * * 読み込んだBean定義ファイルに定義したBeanを試験コード中で使用する場合、以下の二種類のBean取得方法があります。 * * 1. {@link org.springframework.context.ApplicationContext#getBean(String)}によって取得する方法 * 2. setterを定義してautowire(by type)する方法 * * 以下のような定義がある場合を例にとって説明します。 * * WEB-INF/foo/fooContext.xml * * <!-- 前後略 --> * <bean id="foo" class="com.example.Foo" /> * <bean name="/foo" class="com.example.FooBLogic" /> * * 1. {@link org.springframework.context.ApplicationContext#getBean(String)}によって取得する方法 * * {@literal @}ContextConfiguration(locations = { "/WEB-INF/foo/fooContext.xml" }, loader = DaoTestCaseContextLoader.class) * public FooTest extends {@link DaoTestCaseJunit4} { * public void testDoSomething() throws Exception { * Foo foo = getBean("foo"); * // あるいは Foo foo = (Foo) applicationContext.getBean("foo"); * int result = foo.doSomething(); * assertEquals(1, result); * } * } * * {@literal @}ContextConfiguration(locations = { "/WEB-INF/foo/fooContext.xml" }, loader = DaoTestCaseContextLoader.class) * public FooBLogicTest extends {@link DaoTestCaseJunit4} { * public void testFoo() throws Exception { * FooBLogic foo = getBean("/foo"); * // あるいは FooBLogic foo = (FooBLogic) applicationContext.getBean("/foo"); * BLogicResult result = foo.execute(null); * {@link AssertUtils}.assertBLogicSuccess(result); * } * } * * 取得するBeanのインターフェイスにAOP処理を設定している場合は、変数の型をAOP対象のインターフェイスにする必要があります。 * * 2. setterを定義してautowire(by type)する方法 * 取得したいBeanのセッターを定義してください。 * * {@literal @}ContextConfiguration(locations = { "/WEB-INF/foo/fooContext.xml" }, loader = DaoTestCaseContextLoader.class) * public FooTest extends {@link DaoTestCaseJunit4} { * private Foo foo; * * public void setFoo(Foo foo) { * this.foo = foo; * } * * public void testDoSomething() throws Exception { * int result = foo.doSomething(); * assertEquals(1, result); * } * } * * {@literal @}ContextConfiguration(locations = { "/WEB-INF/foo/fooContext.xml" }, loader = DaoTestCaseContextLoader.class) * public FooBLogicTest extends {@link DaoTestCaseJunit4} { * private FooBLogic foo; * * public void setFoo(FooBLogic foo) { * this.foo = foo; * } * * public void testFoo() throws Exception { * BLogicResult result = foo.execute(null); * {@link AssertUtils}.assertBLogicSuccess(result); * } * } * * <strong>この方法は以下の場合には利用できません。</strong> * ・Bean定義ファイル中に同じ型のBeanが複数定義されている場合 * ・AOP処理により{@link ApplicationContext}から{@link java.lang.reflect.Proxy}実装クラスとして取得される場合 * * 本クラスを継承したテストは以下の様に処理が行われる * - テスト実行初回時 * -- WEBAPディレクトリ(コンテキストルート)のクラスパスへの追加({@link TestCaseUtils#getConfigLocationsForDaoTestCase(String[])}) * - 前処理 * -- {@link ApplicationContext}作成 * -- トランザクション開始前前処理({@link #onSetUpBeforeTransaction()}で実装可) * -- トランザクション開始後前処理({@link #onSetUpInTransaction()}で実装可) * * - 試験実行 * * - 後処理 * -- トランザクション終了前後処理({@link #onTearDownInTransaction()})で実装可 * -- トランザクション終了後後処理({@link #onTearDownAfterTransaction()}で実装可) * * </pre> */ @TestExecutionListeners(value = { TransactionalTestExecutionListener.class, DaoTestCaseExecutionListener.class, DirtiesContextTestExecutionListener.class }, inheritListeners = false) abstract public class DaoTestCaseJunit4 extends AbstractTransactionalJUnit4SpringContextTests { /** * AUTOWIRE_NO */ protected static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO; /** * AUTOWIRE_BY_NAMe */ protected static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; /** * AUTOWIRE_BY_TYPE */ protected static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE; /** * AUTOWIRE_CONSTRUCTOR */ protected static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR; /** * AUTOWIRE_AUTODETECT */ @SuppressWarnings("deprecation") protected static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT; /** * autowireモード */ private int autowireMode = AUTOWIRE_BY_TYPE; /** * 依存性チェックを行うか */ private boolean dependencyCheck = false; /** * autowireモードを返却します。 * * @return autowireモード */ public int getAutowireMode() { return autowireMode; } /** * 依存性チェックを行うかを返却します。 * * @return 依存性チェックを行うか */ public boolean isDependencyCheck() { return dependencyCheck; } /** * トランザクション開始前前処理 * * @throws Exception */ @BeforeTransaction public final void setUpBeforeTransaction() throws Exception { onSetUpBeforeTransaction(); } /** * トランザクション開始前前処理 * * @throws Exception */ protected void onSetUpBeforeTransaction() throws Exception { } /** * トランザクション開始後前処理 * * @throws Exception */ @Before public final void setUpInTransaction() throws Exception { onSetUpInTransaction(); } /** * トランザクション開始後前処理 * * @throws Exception */ protected void onSetUpInTransaction() throws Exception { } /** * トランザクション終了前後処理 * * @throws Exception */ @After public final void tearDownInTranscation() throws Exception { onTearDownInTransaction(); } /** * トランザクション終了前後処理 * * @throws Exception */ protected void onTearDownInTransaction() throws Exception { } /** * トランザクション終了後後処理 * * @throws Exception */ @AfterTransaction public final void tearDownAfterTransaction() throws Exception { } /** * トランザクション終了後後処理 * * @throws Exception */ protected void onTearDownAfterTransaction() throws Exception { } /** * Beanを取得します。 * * @param <T> 取得するBeanの型 * @param name beanのidまたはname * @return 取得したBean */ @SuppressWarnings("unchecked") public <T> T getBean(String name) { Assert.notNull(applicationContext, "applicationContext is null!"); return (T) applicationContext.getBean(name); } public JdbcOperations getJdbcTemplate() { return jdbcTemplate; // return simpleJdbcTemplate.getJdbcOperations(); } public int deleteFromTable(String name) { return super.deleteFromTables(new String[] { name }); } // 以下JdbcTemplateUtilsのラッパー /** * @param sql * @return * @throws DataAccessException * @see jp.terasoluna.fw.batch.unit.util.JdbcTemplateUtils#update(org.springframework.jdbc.core.JdbcTemplate, java.lang.String) */ public int update(String sql) throws DataAccessException { return JdbcTemplateUtils.update(getJdbcTemplate(), sql); } /** * @param <T> * @param sql * @param clazz * @return * @throws DataAccessException * @see jp.terasoluna.fw.batch.unit.util.JdbcTemplateUtils#queryForRowObject(org.springframework.jdbc.core.JdbcTemplate, java.lang.String, java.lang.Class) */ public <T> T queryForRowObject(String sql, Class<T> clazz) throws DataAccessException { return JdbcTemplateUtils.queryForRowObject(getJdbcTemplate(), sql, clazz); } /** * @param <T> * @param sql * @param args * @param clazz * @return * @throws DataAccessException * @see jp.terasoluna.fw.batch.unit.util.JdbcTemplateUtils#queryForRowObject(org.springframework.jdbc.core.JdbcTemplate, java.lang.String, java.lang.Object[], java.lang.Class) */ public <T> T queryForRowObject(String sql, Object[] args, Class<T> clazz) throws DataAccessException { return JdbcTemplateUtils.queryForRowObject(getJdbcTemplate(), sql, args, clazz); } }