交互测试接口的简单实现
1. 问题
或者你已经习惯了写 Hardcode JUnit Test Case。但这里有问题:
l 你写的代码要经过 Java compiler 才可运行,但实际的环境下不一定允许这样
l 很难用于交互测试与开发期的错误跟踪。不能要求你的交互测试环境总有一个 Java IDE。
上述问题在 Java Application 的 RMI 接口测试和错误跟踪时就更明显。
2. 解决方法
要做交互测试与错误跟踪,要面对的情况是不可料的,故很难用 Hardcode 的静态语言 Java 去做。但我对动态语言(如 BeanShell )也不大了解。但相对比较了解 Java 的反射机制与 XStream(http://xstream.codehaus.org/) 的从 XML 文本到 Java Object 的应用
Java 的 reflect(反射) + XStream 的 文本到 Object instance :
publicclass MyMethodInfo implements Comparable<MyMethodInfo> {
public Method method;
public MyMethodInfo(Method method) {
this.method = method;
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append( method.getName() ).append( " (" );
Class[] params = method.getParameterTypes();
for( int i = 0 ; i < params.length; i++ ) {
builder.append( params[i].getSimpleName() );
if( i < params.length - 1 ) {
builder.append( ", " );
}
}
builder.append( ')' );
return builder.toString();
}
publicint compareTo(MyMethodInfo o) {
returnthis.method.getName().compareTo( o.method.getName() );
}
}
publicclass MethodArgPanel extends JPanel {
privatestaticfinallongserialVersionUID = 1L;
private JScrollPane jScrollPane = null;
private JTextArea argTextArea = null;
/**
*Thisisthedefaultconstructor
*/
public MethodArgPanel() {
super();
initialize();
}
/**
*Thismethodinitializesthis
*
*@returnvoid
*/
privatevoid initialize() {
this.setSize(246, 230);
this.setLayout(new BorderLayout());
this.add(getJScrollPane(), BorderLayout.CENTER);
}
/**
*ThismethodinitializesjScrollPane
*
*@returnjavax.swing.JScrollPane
*/
private JScrollPane getJScrollPane() {
if ( jScrollPane == null ) {
jScrollPane = new JScrollPane();
jScrollPane.setViewportView(getArgTextArea());
}
returnjScrollPane;
}
/**
*ThismethodinitializesargTextArea
*
*@returnjavax.swing.JTextArea
*/
private JTextArea getArgTextArea() {
if ( argTextArea == null ) {
argTextArea = new JTextArea();
}
returnargTextArea;
}
public String getText() {
returnargTextArea.getText();
}
} // @jve:decl-index=0:visual-constraint="10,10"
publicclass MainFrame extends JFrame {
privatestaticfinallongserialVersionUID = 1L;
private JPanel jContentPane = null;
private JSplitPane mainSplitPane = null;
private JSplitPane leftSplitPane = null;
private JPanel cmdPanel = null;
private JButton execButton = null;
private JScrollPane argsScrollPane = null;
private JPanel argsPanel = null;
private JScrollPane resultScrollPane = null;
private JTextArea resultTextArea = null;
private JScrollPane methodScrollPane = null;
private JList methodList = null;
private MethodArgPanel[] methodArgPanels;
private Object proxy;
/**
*ThismethodinitializesmainSplitPane
*
*@returnjavax.swing.JSplitPane
*/
private JSplitPane getMainSplitPane() {
if ( mainSplitPane == null ) {
mainSplitPane = new JSplitPane();
mainSplitPane.setDividerLocation( 200 );
mainSplitPane.setRightComponent( getLeftSplitPane() );
mainSplitPane.setLeftComponent( getMethodScrollPane() );
}
returnmainSplitPane;
}
/**
*ThismethodinitializesleftSplitPane
*
*@returnjavax.swing.JSplitPane
*/
private JSplitPane getLeftSplitPane() {
if ( leftSplitPane == null ) {
leftSplitPane = new JSplitPane();
leftSplitPane.setOrientation( JSplitPane.VERTICAL_SPLIT );
leftSplitPane.setDividerSize( 8 );
leftSplitPane.setDividerLocation( 400 );
leftSplitPane.setBottomComponent( getResultScrollPane() );
leftSplitPane.setTopComponent( getCmdPanel() );
}
returnleftSplitPane;
}
/**
*ThismethodinitializescmdPanel
*
*@returnjavax.swing.JPanel
*/
private JPanel getCmdPanel() {
if ( cmdPanel == null ) {
cmdPanel = new JPanel();
cmdPanel.setLayout( new BorderLayout() );
cmdPanel.setPreferredSize( new Dimension( 400, 400 ) );
cmdPanel.add( getExecButton(), BorderLayout.EAST );
cmdPanel.add( getArgsScrollPane(), BorderLayout.CENTER );
}
returncmdPanel;
}
/**
*ThismethodinitializesexecButton
*
*@returnjavax.swing.JButton
*/
private JButton getExecButton() {
if ( execButton == null ) {
execButton = new JButton();
execButton.setText( "Exec" );
execButton.addActionListener( new java.awt.event.ActionListener() {
publicvoid actionPerformed(java.awt.event.ActionEvent e) {
MainFrame.this.onExec();
}
} );
}
returnexecButton;
}
/**
*ThismethodinitializesargsScrollPane
*
*@returnjavax.swing.JScrollPane
*/
private JScrollPane getArgsScrollPane() {
if ( argsScrollPane == null ) {
argsScrollPane = new JScrollPane();
argsScrollPane.setPreferredSize( new Dimension( 1, 400 ) );
argsScrollPane.setViewportView( getArgsPanel() );
}
returnargsScrollPane;
}
/**
*ThismethodinitializesargsPanel
*
*@returnjavax.swing.JPanel
*/
private JPanel getArgsPanel() {
if ( argsPanel == null ) {
GridLayout gridLayout = new GridLayout();
gridLayout.setRows( 1 );
argsPanel = new JPanel();
argsPanel.setLayout( gridLayout );
}
returnargsPanel;
}
/**
*ThismethodinitializesresultScrollPane
*
*@returnjavax.swing.JScrollPane
*/
private JScrollPane getResultScrollPane() {
if ( resultScrollPane == null ) {
resultScrollPane = new JScrollPane();
resultScrollPane.setViewportView( getResultTextArea() );
}
returnresultScrollPane;
}
/**
*ThismethodinitializesresultTextArea
*
*@returnjavax.swing.JTextArea
*/
private JTextArea getResultTextArea() {
if ( resultTextArea == null ) {
resultTextArea = new JTextArea();
}
returnresultTextArea;
}
/**
*Thisisthedefaultconstructor
*/
public MainFrame() {
super();
methodArgPanels = new MethodArgPanel[0];
initialize();
}
/**
*Thismethodinitializesthis
*
*@returnvoid
*/
privatevoid initialize() {
this.setSize( 792, 598 );
this.setContentPane( getJContentPane() );
this.setTitle( "EdgeServer Simple Manager" );
}
/**
*ThismethodinitializesjContentPane
*
*@returnjavax.swing.JPanel
*/
private JPanel getJContentPane() {
if ( jContentPane == null ) {
jContentPane = new JPanel();
jContentPane.setLayout( new BorderLayout() );
jContentPane.add( getMainSplitPane(), BorderLayout.CENTER );
}
returnjContentPane;
}
/**
*ThismethodinitializesmethodScrollPane
*
*@returnjavax.swing.JScrollPane
*/
private JScrollPane getMethodScrollPane() {
if ( methodScrollPane == null ) {
methodScrollPane = new JScrollPane();
methodScrollPane.setViewportView( getMethodList() );
}
returnmethodScrollPane;
}
/**
*ThismethodinitializesmethodList
*
*@returnjavax.swing.JList
*/
private JList getMethodList() {
if ( methodList == null ) {
methodList = new JList();
methodList
.addListSelectionListener( new javax.swing.event.ListSelectionListener() {
publicvoid valueChanged(
javax.swing.event.ListSelectionEvent e) {
onMethodChanged();
}
} );
}
returnmethodList;
}
publicvoid setProxyObject(Object proxy) {
this.proxy = proxy;
//List all methods in <code>proxy</code>
setMethods( proxy );
}
privatevoid setMethods(Object proxy) {
Method[] methods = proxy.getClass().getMethods();
MyMethodInfo[] infos = new MyMethodInfo[methods.length];
for (int i = 0; i < methods.length; i++) {
infos[i] = new MyMethodInfo( methods[i] );
}
Arrays.sort( infos );
methodList.setListData( infos );
}
privatevoid onMethodChanged() {
argsPanel.removeAll();
MyMethodInfo mi = (MyMethodInfo) methodList.getSelectedValue();
if ( mi == null ) {
methodArgPanels = new MethodArgPanel[0];
return;
}
int argQty = mi.method.getParameterTypes().length;
methodArgPanels = new MethodArgPanel[argQty];
for (int i = 1; i <= argQty; i++) {
methodArgPanels[i - 1] = new MethodArgPanel();
argsPanel.add( methodArgPanels[i - 1] );
}
argsPanel.repaint();
argsPanel.revalidate();
}
privatevoid onExec() {
StringBuilder result = new StringBuilder();
result.append( "====================================\n" );
//get the method user selected
MyMethodInfo mi = (MyMethodInfo) methodList.getSelectedValue();
if ( mi == null ) {
result.append( "No method called" );
resultTextArea.setText( result.toString() );
return;
}
Object[] args = new Object[mi.method.getParameterTypes().length];
XStream xstream = new XStream( new DomDriver() );
try {
//convert the arg objects from xml text
for (int i = 0; i < this.methodArgPanels.length; i++) {
args[i] = xstream.fromXML( methodArgPanels[i].getText() );
}
//invoke the method
Object invokeResult = mi.method.invoke( proxy, args );
//convert the result to xml text
result.append( "Return val:\n" );
result.append( xstream.toXML( invokeResult ) );
}
catch ( Throwable e ) {
//Exception handle
StringWriter sw = new StringWriter();
PrintWriter printWriter = new PrintWriter( sw );
e.printStackTrace( printWriter );
result.append( "Cache Exception:\n" );
result.append( sw );
printWriter.close();
e.printStackTrace();
}
//show the invoke result in UI
resultTextArea.setText( result.toString() );
}
} // @jve:decl-index=0:visual-constraint="10,56"