本来今天已经完成了框架的大部分功能,写的一些测试用例都可以成功执行,但是自动发布是放在BaseTestCase里面的,感觉不好,就重构了一下,扩展了InitialContext类,覆盖了lookup方法(参数为字符串的那个,我们的代码中都是使用的这个),这样代码看起来更好一些的。另外我们的系统里面使用到了一些类似的机制,我为了产品可以进行单元测试还对一些Factory类进行了简单的修改,让他们返回我为了单元测试而写的实现类。如果使用这个扩展的InitialContext类,应该不需要做那些修改了,试了下,发现不行,因为产品的代码好像和Jboss的某些特性进行绑定了,先做简单的重构,以后再研究产品到底使用了JBoss的哪些特性,能否搞定。
代码如下:
package test.base;
import java.lang.reflect.Method;
import java.util.Iterator;
import javax.jms.MessageListener;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.mockejb.EntityBeanDescriptor;
import org.mockejb.MDBDescriptor;
import org.mockejb.MockContainer;
import org.mockejb.SessionBeanDescriptor;
import org.mockejb.interceptor.Aspect;
import org.mockejb.interceptor.AspectSystem;
import org.mockejb.interceptor.ClassPointcut;
import org.mockejb.interceptor.InvocationRecorder;
import test.util.ClassUtil;
import test.util.CommandUtil;
import test.util.DataUtil;
import test.util.DummyDataUtil;
import test.util.EJBUtil;
public class ARInitialContext extends InitialContext
{
private static Logger log = LogManager.getLogger(ARInitialContext.class);
private MockContainer mockContainer;
private AspectSystem aspectSystem;
public ARInitialContext() throws NamingException
{
}
/**
* @return the mockContainer
*/
public MockContainer getMockContainer()
{
return mockContainer;
}
/**
* @param mockContainer the mockContainer to set
*/
public void setMockContainer(MockContainer mockContainer)
{
this.mockContainer = mockContainer;
}
/**
* @return the aspectSystem
*/
public AspectSystem getAspectSystem()
{
return aspectSystem;
}
/**
* @param aspectSystem the aspectSystem to set
*/
public void setAspectSystem(AspectSystem aspectSystem)
{
this.aspectSystem = aspectSystem;
}
/**
* Lookup responding object, if not existed, try to init it.
* First try to init from custom init method(init+jndiName’s final part),
* if failed, try to get BeanInfo from config file and init it.
* @param jndiName
* @return
* @throws Exception
*/
public Object lookup(String jndiName) throws NamingException
{
return lookup(jndiName, true);
}
public Object lookup(String jndiName, boolean tryInit) throws NamingException
{
Object objRef = null;
try
{
objRef = super.lookup(jndiName);
if (objRef != null)
{
return objRef;
}
}
catch (NamingException e)
{
}
if (tryInit)
{
return tryToInitBean(jndiName);
}
else
{
return objRef;
}
}
/**
* Init bean according to BeanInfo, can init entity bean, session bean and message driven bean.
* @param jndi
* @param beanInfo
* @throws Exception
*/
private void initBean(String jndi, BeanInfo beanInfo) throws Exception
{
log.debug("Init bean:" + beanInfo.getShortName() + ", JNDI:" + jndi);
if (beanInfo.getType() == BeanInfo.ENTITY_BEAN)
{
initEntityBean(jndi, beanInfo);
}
else if (beanInfo.getType() == BeanInfo.SESSION_BEAN)
{
initSessionBean(jndi, beanInfo);
}
else if (beanInfo.getType() == BeanInfo.MESSAGE_BEAN)
{
initMessageBean(beanInfo);
}
else
{
log.error("Unsupported bean type: " + beanInfo.getType());
}
}
/**
* Init message bean, if the jndi name is start with "topic/", then it is topic type, otherwise, it is queue type.
* The factory also is depending on its jndi name.
* @param beanInfo
* @throws Exception
*/
private void initMessageBean(BeanInfo beanInfo) throws Exception
{
Class bean = ClassUtil.getClassForName(beanInfo.getBean());
String jndi = beanInfo.getJndi();
String factoryJndi = null;
if (jndi.startsWith(Constant.TOPIC))
{
factoryJndi = Constant.TOPIC_CONNECTION_FACTORY;
}
else
{
factoryJndi = Constant.QUEUE_CONNECTION_FACTORY;
}
MDBDescriptor descriptor = new MDBDescriptor(factoryJndi, jndi, bean.newInstance());
if (jndi.startsWith(Constant.TOPIC))
{
descriptor.setIsTopic(true);
}
mockContainer.deploy(descriptor);
InvocationRecorder recorder = new InvocationRecorder();
aspectSystem.add(new ClassPointcut(MessageListener.class, false), recorder);
}
public void initQueueConnectionFactory(String factoryJndi) throws Exception
{
MDBDescriptor descriptor = new MDBDescriptor(factoryJndi, Constant.MOCK_QUEUE, new BaseMessageBean());
descriptor.setIsTopic(false);
mockContainer.deploy(descriptor);
}
public void initTopicConnectionFactory(String factoryJndi) throws Exception
{
MDBDescriptor descriptor = new MDBDescriptor(factoryJndi, Constant.MOCK_TOPIC, new BaseMessageBean());
descriptor.setIsTopic(true);
mockContainer.deploy(descriptor);
}
private Object tryToInitBean(String jndiName)
{
try
{
BeanInfo beanInfo = EJBUtil.getBeanInfoByJndi(jndiName);
if (beanInfo == null)
{
log.error("Can not find BeanInfo for " + jndiName);
return null;
}
else
{
initBean(jndiName, beanInfo);
}
return super.lookup(jndiName);
}
catch (Exception e)
{
log.error("Can not init bean:" + jndiName);
return null;
}
}
/**
* Inint entity bean and create all dummy record from dummy xml database.
* @param jndi
* @param beanInfo
* @throws Exception
*/
private void initEntityBean(String jndi, BeanInfo beanInfo) throws Exception
{
Class home = ClassUtil.getClassForName(beanInfo.getHome());
Class remote = ClassUtil.getClassForName(beanInfo.getRemote());
Class bean = ClassUtil.getClassForName(beanInfo.getBean());
Class create = ClassUtil.getClassForName(Constant.ASPECT_PACKAGE + beanInfo.getShortName() + "CreateAspect");
Class find = ClassUtil.getClassForName(Constant.ASPECT_PACKAGE + beanInfo.getShortName() + "FindAspect");
Class setter = ClassUtil.getClassForName(Constant.ASPECT_PACKAGE + beanInfo.getShortName() + "SetterAspect");
Aspect createAspect = null;
Aspect findAspect = null;
Aspect setterAspect = null;
if (create != null)
{
createAspect = (Aspect) create.getConstructor(new Class[]
{ BeanInfo.class }).newInstance(new Object[]
{ beanInfo });
}
else
{
createAspect = new BaseCreateAspect(beanInfo);
}
if (find != null)
{
findAspect = (Aspect) find.getConstructor(new Class[]
{ BeanInfo.class }).newInstance(new Object[]
{ beanInfo });
}
else
{
findAspect = new BaseFindAspect(beanInfo);
}
if (setter != null)
{
setterAspect = (Aspect) setter.getConstructor(new Class[]
{ BeanInfo.class }).newInstance(new Object[]
{ beanInfo });
}
else
{
setterAspect = new BaseSetterAspect(beanInfo);
}
aspectSystem.add(createAspect);
aspectSystem.add(findAspect);
aspectSystem.add(setterAspect);
EntityBeanDescriptor descriptor = new EntityBeanDescriptor(jndi, home, remote, bean);
mockContainer.deploy(descriptor);
Object homeObject = lookup(jndi);
try
{
Method createMethod = ClassUtil.getMostSimpleCreateMethod(homeObject);
Class[] parameterTypes = createMethod.getParameterTypes();
Object[] values = new Object[parameterTypes.length];
Iterator pks = DummyDataUtil.getPkValues(EJBUtil.getBeanInfoByJndi(jndi).getShortName()).iterator();
while (pks.hasNext())
{
Long pk = (Long) pks.next();
DataUtil.setPk(beanInfo.getShortName(), pk);
createMethod.invoke(homeObject, values);
}
CommandUtil.executeCommands();
}
catch (Exception e)
{
log.warn("Can not init dummy data for " + jndi, e);
try
{
DummyDataUtil.initDatabaseInfo(beanInfo);
}
catch (Exception e1)
{
log.warn("Can not init database info for " + jndi, e);
}
}
}
/**
* Init session bean, maybe local type, depending on the jndi name
* @param jndi
* @param beanInfo
* @throws Exception
*/
private void initSessionBean(String jndi, BeanInfo beanInfo) throws Exception
{
Class home = null;
Class remote = null;
Class bean = ClassUtil.getClassForName(beanInfo.getBean());
if (jndi.equals(beanInfo.getJndi()))
{
home = ClassUtil.getClassForName(beanInfo.getHome());
remote = ClassUtil.getClassForName(beanInfo.getRemote());
}
else
{
home = ClassUtil.getClassForName(beanInfo.getLocalHome());
remote = ClassUtil.getClassForName(beanInfo.getLocal());
}
Class aspectClass = ClassUtil.getClassForName(Constant.ASPECT_PACKAGE + beanInfo.getShortName() + "Aspect");
Aspect aspect = null;
if (aspectClass != null)
{
aspect = (Aspect) aspectClass.getConstructor(new Class[]
{ BeanInfo.class }).newInstance(new Object[]
{ beanInfo });
aspectSystem.add(aspect);
}
SessionBeanDescriptor descriptor = new SessionBeanDescriptor(jndi, home, remote, bean);
mockContainer.deploy(descriptor);
}
public void deploySessionBean(String jndi, Class home, Class remote, Object bean) throws Exception
{
SessionBeanDescriptor descriptor = new SessionBeanDescriptor(jndi, home, remote, bean);
mockContainer.deploy(descriptor);
}
}
0 Comments
2 Pingbacks