2012年9月7日 星期五

財稅案DBUnit測試重購

在財稅案的單元測試中使用DBUnit,來進行DAO的unit Test, 但是因為原本的寫法有點雜亂,所以來調整一下 在財稅案的單元測試中使用DBUnit,來進行DAO的unit Test, 但是因為原本的寫法有點雜亂,所以來調整一下 原本寫法

@DataSetLocation("classpath:/gov/fdc/tac/TACT005_dataset.xml")
public class TACT005DaoImplTest extends AbstractTACCoreTests {
    Logger logger = LoggerFactory.getLogger(TACT005DaoImplTest.class);
 
    TACT005Dao TACT005Dao;
    
    @PersistenceContext
    private EntityManager entityManager;
    
 @Before
 public void setUp() throws Exception {
  TACT005Dao = new TACT005DaoImpl();
  JPQLLoader jpqlLoader = new JPQLLoader();
  jpqlLoader.setApplicationContext(applicationContext);
  jpqlLoader.initJPQL();
        //取得openJPA entity的連線設定
        for (Field field : OpenJPADaoImpl.class.getDeclaredFields()) {
            if (EntityManager.class.isAssignableFrom(field.getType())) {
                field.setAccessible(true);
                field.set(TACT005Dao, entityManager);
            }
            if (JPQLLoader.class.isAssignableFrom(field.getType())) {
                field.setAccessible(true);
                field.set(TACT005Dao, jpqlLoader);
            }
        }
 }
 
 @Test
 public void testTACT005(){
     TACT005 tact005 = TACT005Dao.query(new TACT005(), new TACT005PK());
  assertNotNull(tact005);
 }
 

可以看到setUp中有很多固定的寫法,這些是可以抽出來的...於是我就把他pull up了~ 在父類別AbstractTACCoreTests去處理這些無聊的事情,就是說「想要嗎?爸爸買給你~」這樣。

public class AbstractTACCoreTests extends AbstractSDPUserAwareTests {
    public Logger logger = LoggerFactory.getLogger(getClass());

    private JPQLLoader jpqlLoader;

    @PersistenceContext
    private EntityManager entityManager;
    private AsYouWishEntityManagerSelector emSelector;

    /**初始化單元測試類別,進行物件的實作及注入相關類別
     * @param targetObj
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws SecurityException
     * @throws NoSuchFieldException
     * @throws IOException
     */
    public void init(Object targetObj) throws IllegalArgumentException, IllegalAccessException, SecurityException,
            NoSuchFieldException, IOException {
        List injectDaoList = new ArrayList();
        Object managerImpl = null;
        for (Field f : targetObj.getClass().getDeclaredFields()) {
            if (f.isAnnotationPresent(InjectTACTest.class)
                    && (f.getType().getName().indexOf("Dao") >= 0 || f.getType().getName().indexOf("Manager") >= 0)) {
                String implObjNm = f.getType().getName();
                logger.info("符合條件的FIELD:" + implObjNm);
                // 取得實作類別的完整名稱
                implObjNm = getImplObjName(implObjNm);
                try {
                    Object implObjInstance = Class.forName(implObjNm).newInstance();
                    logger.info(implObjNm + "建立成功!");
                    boolean isAccessable = f.isAccessible();
                    if (!(isAccessable)) {
                        f.setAccessible(true);
                    }
                    //設定實作類別給單元測試物件
                    managerImpl = setField(targetObj, injectDaoList, f, implObjInstance);
                    logger.info(implObjNm + "assign成功!");
                } catch (Exception e) {
                    logger.error(implObjNm + "建立失敗!");
                    e.printStackTrace();
                }
            }
        }
        //將dao必要欄位 注入 jpqlLoader及 EntityManager
        initDao(injectDaoList);
        if (null != managerImpl) {
            //將dao注入到manager中
            initManager(managerImpl, injectDaoList);
        }
    }

    /**
     * 將dao必要欄位 注入 jpqlLoader及 EntityManager
     * 
     * @param injectDaoList
     *            injectDaoList
     * @throws IllegalArgumentException
     *             IllegalArgumentException
     * @throws IllegalAccessException
     *             IllegalAccessException
     * @throws NoSuchFieldException
     * @throws SecurityException
     * @throws IOException
     */
    public void initDao(List injectDaoList) throws IllegalArgumentException, IllegalAccessException, SecurityException,
            NoSuchFieldException, IOException {
        if (jpqlLoader == null) {
            jpqlLoader = new JPQLLoader();
            jpqlLoader.setApplicationContext(applicationContext);
            jpqlLoader.initJPQL();
        }
        if (null == emSelector) {
            emSelector = new AsYouWishEntityManagerSelector(entityManager);
        }
        for (Object dao : injectDaoList) {
            ObjectRobber.set(dao, "entityManagerSelector", emSelector);
            ObjectRobber.set(dao, "jpqlLoader", jpqlLoader);
            logger.info(dao.getClass().getName() + "注入成功!");
        }
    }

    /**
     * 將dao注入到manager中
     * 
     * @param managerImpl
     *            managerImpl
     * @param injectDaoList
     *            injectDaoList
     * @throws SecurityException
     *             SecurityException
     * @throws IllegalAccessException
     *             IllegalAccessException
     */
    public void initManager(Object managerImpl, List injectDaoList) throws SecurityException,
            IllegalAccessException {
        for (Dao dao : injectDaoList) {
            // Dao取得entity連線後注入APPBasicSampleManagerImpl
            ObjectRobber.manualWire(managerImpl, dao);
        }
    }

    /**設定實作類別給單元測試物件
     * @param targetObj
     * @param injectDaoList
     * @param feild
     * @param implObjInstance
     * @return
     * @throws IllegalAccessException
     */
    private Object setField(Object targetObj, List injectDaoList, Field feild, Object implObjInstance)
            throws IllegalAccessException {
        String implObjNm = feild.getType().getName();
        Object managerImpl = null;
        feild.set(targetObj, implObjInstance);
        if (implObjNm.indexOf("DaoImpl") == -1) {
            injectDaoList.add(implObjInstance);
        }else if (implObjNm.indexOf("ManagerImpl") == -1) {
            managerImpl = implObjInstance;
        }
        return managerImpl;
    }

    /**取得實作類別的完整名稱
     * @param objNm
     * @return implObjNm
     */
    private String getImplObjName(String objNm) {
        String implObjNm = objNm;
        if (objNm.indexOf("DaoImpl") == -1) {
            int idx = objNm.lastIndexOf(".");
            implObjNm = objNm.substring(0, idx) + ".impl" + objNm.substring(idx, objNm.length()) + "Impl";
        }else if (objNm.indexOf("ManagerImpl") == -1) {
            int idx = objNm.lastIndexOf(".");
            implObjNm = objNm.substring(0, idx) + ".impl" + objNm.substring(idx, objNm.length()) + "Impl";
        }
        return implObjNm;
    }

同時還寫了一個annotaion作為標記使用。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectTACTest {}

這樣子整理過後的單元測試程式就乾淨多了。 易容後效果如下:

@DataSetLocation("classpath:/gov/fdc/tac/TACT005_dataset.xml")
public class TACT005DaoImplTest extends AbstractTACCoreTests {
    Logger logger = LoggerFactory.getLogger(TACT005DaoImplTest.class);
 
    @InjectTACTest
    TACT005Dao TACT005Dao;
    
 @Before
 public void setUp() throws Exception {
  init(this);
 }
 @Test
 public void testTACT005(){
     TACT005 tact005 = TACT005Dao.query(new TACT005(), new TACT005PK());
  assertNotNull(tact005);
 }

這樣是不是爽多了~~

沒有留言:

張貼留言