模拟对象(二)

本文介绍了借助easymock进行GUI测试的方法。先探讨获取GUI组件的方式,采用JavaBean思想提供get方法。接着给出测试接口、GUI代码及测试程序示例,演示了简单测试组件是否存在和复杂测试组件功能的过程,还提及easymock使用要点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      上一篇中我简单介绍了一下Mock ,今天我就来说明一下怎么借助easymock来进行GUI的测试。
     关于easymock的安装请参见它的说明文档,这里就不再介绍了。
     在进行测试前,我们先要有个问题要解决:那就是怎么在测试代码中得到GUI中的各个组件(比如JButton)?也许你会说将它们定义为public就可以了,但这却不太符合面向对象中的封装思想。用反射?也不错,但好像太复杂了,为了一个测试好像没有必要。当然我们可以利用一些其他的辅助测试工具,比如JFCUnit,这些我会在下一篇中介绍。现在,就假设我们不知道有第三方的其他工具,那怎么办呢?我的做法是借用JavaBean的思想——提供一个get方法。
       好了,下面就开始具体的操作了。
       首先,我们就假设要测试的GUI定义一个接口,简单点,如下示:
      package TestGUI;
     import java.util.*;
      public interface ListEditor {
      Vector getNames();
      void add(String name);
     void delete(int index);
     }
    然后,我们就可以写测试程序了(假如你采用的是TDD的话),但我们这里只是要演示easymock在测试GUI中的用处,所以我们不这样做,我们先写好GUI的代码,如下:
package TestGUI;
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
public class ListWindow
    extends JFrame {
  private JList nameList;
  private JButton addButton;
  private ListEditor myEditor;
  private JTextField nameField;
  public ListWindow(ListEditor myEditor) {
    super();
    this.myEditor = myEditor;
  }
  public JList getNameList() {
    return nameList;
  }
  public JButton getAddButton() {
    return addButton;
  }
  public JTextField getNameField() {
    return nameField;
  }
  public void init() {
     setLayout();
    initList();
    initAddButton();
    initField();
    this.setSize(300, 200);
    // this.pack();
  }
  private void setLayout() {
    this.getContentPane().setLayout(new FlowLayout());
  }
  private void initList() {
    nameList = new JList(getNames());
    JScrollPane scroll = new JScrollPane(nameList);
    this.getContentPane().add(scroll);
  }
  private void initAddButton() {
    addButton = new JButton("Add");
    addButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        myEditor.add(nameField.getText());
        movieList.setListData(getNames());
      }
    });
    this.getContentPane().add(addButton);
  }
  private void initField() {
    movieField = new JTextField(13);
    this.getContentPane().add(nameField);
  }
  private Vector getNames() {
    Vector names = myEditor.getNames();
    return (names == null) ? new Vector() : names;
  }
 }
好了,现在一切都准备好了,我们可以来写测试了,如下:
package TestGUI;
import junit.framework.*;
import org.easymock.*;
import javax.swing.*;
public class TestBaseGUI
    extends TestCase {
  private MockControl control;
  private ListEditor mockEditor;
  private ListWindow window;
  protected void setUp() throws Exception {
    super.setUp();
    control = MockControl.createNiceControl(ListEditor.class);
    mockEditor = (ListEditor) control.getMock();
    control.replay();
    window = new ListWindow(mockEditor);
    window.init();
    window.show();
  }
  public void testList() {
    JList nameList = window.getNameList();
    assertNotNull("list not null", nameList);
    assertTrue("is showing", nameList.isShowing());
  }
  public void testAddButton()
  {
    JButton addButton=window.getAddButton() ;
    assertEquals("should be add","Add",addButton.getText() );
  }
  public void testField()
  {
    JTextField nameField=window.getNameField() ;
    assertNotNull("text not null",nameField);
  }
  protected void tearDown() throws Exception {
    super.tearDown();
  }
}
这个测试非常简单,它只是测试GUI上的组件是否真的存在(非空)。本来没有什么意思,但之所以这么简单就是为了更集中的演示easymock的使用。在上面的代码中,我们首先用easymock中MockControl的静态工厂得到了一个MockControl(而且是nice的,这就使你不用去关心它的返回值),然后利用control我们就得到了一个mock并将它强制转换为ListEditor,然后我们就可以用它了(在使用前最好用replay激活它)。就是这么简单,如果这个测试通过了,那说明你的GUI就没有问题了,在具体用到项目中时,你只需要实现一个类,让它implements接口ListEditor ,然后将它传给GUI就可以了。
下面的测试更复杂点,它测试了GUI中各组件的功能,但原理是一样的:
package TestGUI;
import junit.framework.*;
import org.easymock.*;
import java.util.*;
import javax.swing.*;
public class TestMovieListWindow
    extends TestCase {
  private ListWindow ListWindow = null;
  private static final String addString = "Test a mock!";
  private Vector name = null;
  private MockControl control = null;
  private ListEditor mockEditor = null;
  protected void setUp() throws Exception {
    super.setUp();
    /**@todo verify the constructors*/
    name = new Vector() {
      {
        add("Hello");
        add("Hit");
      }
    };
    control = MockControl.createControl(ListEditor.class);
    mockEditor = (ListEditor) control.getMock();
  }
  public void testList() {
    mockEditor.getNames();
    control.setReturnValue(name, 1);
    control.replay();
    window = new ListWindow(mockEditor);
    window.init();
    window.show();
    JList nameList = window.getNameList();
    ListModel nameListModel = nameList.getModel();
    assertEquals("Wrong size", name.size(), nameListModel.getSize());
    assertEquals("should be hello!", "Hello", nameListModel.getElementAt(0));
    control.verify();
  }
  public void testAdd() {
    Vector NameWithAddition = new Vector(name);
    NameWithAddition.add(addString);
    mockEditor.getNames();
    control.setReturnValue(name, 1);
    mockEditor.add(addString);
    control.setVoidCallable(1);
    mockEditor.getNames();
    control.setReturnValue(NameWithAddition, 1);
    control.replay();
    window = new ListWindow(mockEditor);
    window.init();
    window.show();
    JTextField nameField = window.getNameField();
    nameField.setText(addString);
    JButton addButton = window.getAddButton();
    addButton.doClick();
    JList nameList = window.getNameList();
    ListModel nameListModel = nameList.getModel();
    assertEquals("Wrong size", NameWithAddition.size(),
                 nameListModel.getSize());
    assertEquals("should be Test a mock!", addString,
                 nameListModel.getElementAt(2));
    control.verify();
  }
  protected void tearDown() throws Exception {
       super.tearDown();
  }
}
在这个测试中,我们返回的control不是nice的,所以你在每次设置时,都要说明它的返回值和调用的次数,其余的就没有什么变化了。
    关于easymock更多的,请参看它提供的文档。
这次,我们用一种不太优雅的方式利用easymock进行了GUI的测试,下一次,我将演示用一种更好方式来进行测试,同时会介绍有关“超瘦”GUI的概念!
     (代码在Jbuilder2005+xp sp1下通过)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值