交互测试接口的简单实现
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 :
public
class
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();
}
public
int
compareTo(MyMethodInfo o) {
return
this
.
method
.getName().compareTo( o.
method
.getName() );
}
}
|
public
class
MethodArgPanel
extends
JPanel {
private
static
final
long
serialVersionUID
= 1L;
private
JScrollPane
jScrollPane
=
null
;
private
JTextArea
argTextArea
=
null
;
/**
*
This
is
the
default
constructor
*/
public
MethodArgPanel() {
super
();
initialize();
}
/**
*
This
method
initializes
this
*
*
@return
void
*/
private
void
initialize() {
this
.setSize(246, 230);
this
.setLayout(
new
BorderLayout());
this
.add(getJScrollPane(), BorderLayout.
CENTER
);
}
/**
*
This
method
initializes
jScrollPane
*
*
@return
javax.swing.JScrollPane
*/
private
JScrollPane getJScrollPane() {
if
(
jScrollPane
==
null
) {
jScrollPane
=
new
JScrollPane();
jScrollPane
.setViewportView(getArgTextArea());
}
return
jScrollPane
;
}
/**
*
This
method
initializes
argTextArea
*
*
@return
javax.swing.JTextArea
*/
private
JTextArea getArgTextArea() {
if
(
argTextArea
==
null
) {
argTextArea
=
new
JTextArea();
}
return
argTextArea
;
}
public
String getText() {
return
argTextArea
.getText();
}
}
// @jve:decl-index=0:visual-constraint="10,10
"
|
public
class
MainFrame
extends
JFrame {
private
static
final
long
serialVersionUID
= 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
;
/**
*
This
method
initializes
mainSplitPane
*
*
@return
javax.swing.JSplitPane
*/
private
JSplitPane getMainSplitPane() {
if
(
mainSplitPane
==
null
) {
mainSplitPane
=
new
JSplitPane();
mainSplitPane
.setDividerLocation( 200 );
mainSplitPane
.setRightComponent( getLeftSplitPane() );
mainSplitPane
.setLeftComponent( getMethodScrollPane() );
}
return
mainSplitPane
;
}
/**
*
This
method
initializes
leftSplitPane
*
*
@return
javax.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() );
}
return
leftSplitPane
;
}
/**
*
This
method
initializes
cmdPanel
*
*
@return
javax.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
);
}
return
cmdPanel
;
}
/**
*
This
method
initializes
execButton
*
*
@return
javax.swing.JButton
*/
private
JButton getExecButton() {
if
(
execButton
==
null
) {
execButton
=
new
JButton();
execButton
.setText(
"Exec"
);
execButton
.addActionListener(
new
java.awt.event.ActionListener() {
public
void
actionPerformed(java.awt.event.ActionEvent e) {
MainFrame.
this
.onExec();
}
} );
}
return
execButton
;
}
/**
*
This
method
initializes
argsScrollPane
*
*
@return
javax.swing.JScrollPane
*/
private
JScrollPane getArgsScrollPane() {
if
(
argsScrollPane
==
null
) {
argsScrollPane
=
new
JScrollPane();
argsScrollPane
.setPreferredSize(
new
Dimension( 1, 400 ) );
argsScrollPane
.setViewportView( getArgsPanel() );
}
return
argsScrollPane
;
}
/**
*
This
method
initializes
argsPanel
*
*
@return
javax.swing.JPanel
*/
private
JPanel getArgsPanel() {
if
(
argsPanel
==
null
) {
GridLayout gridLayout =
new
GridLayout();
gridLayout.setRows( 1 );
argsPanel
=
new
JPanel();
argsPanel
.setLayout( gridLayout );
}
return
argsPanel
;
}
/**
*
This
method
initializes
resultScrollPane
*
*
@return
javax.swing.JScrollPane
*/
private
JScrollPane getResultScrollPane() {
if
(
resultScrollPane
==
null
) {
resultScrollPane
=
new
JScrollPane();
resultScrollPane
.setViewportView( getResultTextArea() );
}
return
resultScrollPane
;
}
/**
*
This
method
initializes
resultTextArea
*
*
@return
javax.swing.JTextArea
*/
private
JTextArea getResultTextArea() {
if
(
resultTextArea
==
null
) {
resultTextArea
=
new
JTextArea();
}
return
resultTextArea
;
}
/**
*
This
is
the
default
constructor
*/
public
MainFrame() {
super
();
methodArgPanels
=
new
MethodArgPanel[0];
initialize();
}
/**
*
This
method
initializes
this
*
*
@return
void
*/
private
void
initialize() {
this
.setSize( 792, 598 );
this
.setContentPane( getJContentPane() );
this
.setTitle(
"EdgeServer Simple Manager"
);
}
/**
*
This
method
initializes
jContentPane
*
*
@return
javax.swing.JPanel
*/
private
JPanel getJContentPane() {
if
(
jContentPane
==
null
) {
jContentPane
=
new
JPanel();
jContentPane
.setLayout(
new
BorderLayout() );
jContentPane
.add( getMainSplitPane(), BorderLayout.
CENTER
);
}
return
jContentPane
;
}
/**
*
This
method
initializes
methodScrollPane
*
*
@return
javax.swing.JScrollPane
*/
private
JScrollPane getMethodScrollPane() {
if
(
methodScrollPane
==
null
) {
methodScrollPane
=
new
JScrollPane();
methodScrollPane
.setViewportView( getMethodList() );
}
return
methodScrollPane
;
}
/**
*
This
method
initializes
methodList
*
*
@return
javax.swing.JList
*/
private
JList getMethodList() {
if
(
methodList
==
null
) {
methodList
=
new
JList();
methodList
.addListSelectionListener(
new
javax.swing.event.ListSelectionListener() {
public
void
valueChanged(
javax.swing.event.ListSelectionEvent e) {
onMethodChanged();
}
} );
}
return
methodList
;
}
public
void
setProxyObject(Object proxy) {
this
.
proxy
= proxy;
//List all methods in <code>proxy</code>
setMethods( proxy );
}
private
void
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 );
}
private
void
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();
}
private
void
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
"
|