当尝试使用AssertJ的pressAndReleaseKeys()模拟输入以在Java Swing程序中对JComboBox进行单元测试时,我没有看到预期的行为。该程序通常会挂在 pressAndReleaseKeys 行上,然后失败,或者偶尔会删除当前正在测试的 JComboBox 中的所有文本,导致以后的断言失败(即 requireSelection())。我收到的有关提供的示例程序(见下文)挂起时的堆栈跟踪如下:
焦点更改为javax.swing.JComboBox[name='combob', selectedItem='Bean', content=["Pork", "Beans", "Rice"], editable=true, enabled=true, visible=true, showing=true] 失败的焦点所有者: javax.swing.plaf.metal.MetalComboBoxEditor$1(javax.swing.JTextField)[name=null, text='Bean', enabled=true, visible=true, showing=true]
org.assertj.swing.exception.ActionFailedException
at org.assertj.swing.exception.ActionFailedException.actionFailure(ActionFailedException.java:33)
at org.assertj.swing.core.BasicRobot.focus(BasicRobot.java:301)
at org.assertj.swing.core.BasicRobot.focusAndWaitForFocusGain(BasicRobot.java:270)at org.assertj.swing.driver.ComponentDriver.focusAndWaitForFocusGain(ComponentDriver.java:419)
at org.assertj.swing.driver.ComponentDriver.pressAndReleaseKeys(ComponentDriver.java:315)
at org.assertj.swing.fixture.AbstractComponentFixture.pressAndReleaseKeys(AbstractComponentFixture.java:293)
at javapractice.ComboBoxSampleTest.testMain(ComboBoxSampleTest.java:59)
我一直在使用 FEST,并希望将我的测试迁移到 AssertJ,因为它正在积极维护,而 FEST 多年来一直没有更新。我使用了Joel Costigliola从Fest到AssertJ指南的迁移,但是在使用pressAndReleaseKeys()模拟键盘输入时遇到问题。我能够在使用 JTextComponentFixture 时模拟输入,即
window.textBox("textB").pressAndReleaseKeys(KeyEvent.VK_LEFT);
(其中 window 是一个 FrameFixture,一个 AssertJ 和 FEST 中的容器),但我在使用 JComboBoxFixture 时无法模拟输入,即
window.comboBox("comboB").pressAndReleaseKeys(KeyEvent.VK_LEFT);
这个障碍通常是可以避免的,因为大多数"按键"都可以通过使用enterText来模拟,即
window.comboBox("comboB").enterText("n"); //to press the enter key
window.comboBox("comboB").enterText("b"); //to press the backspace key
但我希望能够使用箭头键、控制键和其他无法使用 enterText() 模拟按键的键。此失败是由于我的环境*问题、我使用它的方式问题还是 API 本身存在缺陷?
我尝试使用pressKey()然后使用releaseKey()作为解决方法,但这也不适用于JComboBox,我的程序而是挂在pressKey()上。话虽如此,我也不能使用 pressKey() 和 releaseKey() 来测试 JComboBox 和 FEST 。
*环境详细信息:
语言版本:java版本"1.8.0_131">
平台版本(例如.NET 3.5;请注意,这并不总是从语言版本中隐含的,反之亦然)
操作系统:Red Hat Release 6.10(圣地亚哥)
IDE:Netbeans 8.0.2
GUI 应用程序示例:
package javapractice;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class ComboBoxSample extends JFrame implements ItemListener{
JPanel jp;
JComboBox jcb;
JLabel result;
JLabel title;
JTextField jtc;
public static void main(String[] args) {
ComboBoxSample frame = new ComboBoxSample();
}
ComboBoxSample() {
super();
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setTitle("Testing AssertJ");
this.setLayout(new FlowLayout());
jp = new JPanel();
jcb = new JComboBox(new String[] {"Pork", "Beans", "Rice"});
jcb.setEditable(true);
jcb.setName("combob");
jtc = new JTextField();
jtc.setEditable(true);
jtc.setPreferredSize(new Dimension(150, 25));
jtc.setName("textb");
title = new JLabel("Food: ");
result = new JLabel("No food");
jp.add(title);
jp.add(jcb);
jp.add(result);
jp.add(jtc);
this.add(jp);
this.setLocationRelativeTo(null);
jcb.addItemListener(this);
this.pack();
this.repaint();
}
@Override
public void itemStateChanged(ItemEvent e) {
if(e.getSource() == jcb) {
result.setText("I'm eating " + jcb.getSelectedItem());
}
this.pack();
}
public void cleanUp() {
jcb = null;
result = null;
jtc = null;
jp = null;
title = null;
}
}
节日测试文件:
package javapractice;
import com.sun.glass.events.KeyEvent;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Fest imports.
*/
import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.fixture.FrameFixture;
public class ComboBoxSampleTest {
private FrameFixture window;
private ComboBoxSample frame;
@BeforeClass
public static void setUpClass() {
FailOnThreadViolationRepaintManager.install();
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
frame = GuiActionRunner.execute(new GuiQuery<ComboBoxSample>() {
@Override
protected ComboBoxSample executeInEDT() {
return new ComboBoxSample();
}
});
window = new FrameFixture(frame);
window.show();
}
@After
public void tearDown() {
window.cleanUp();
frame.cleanUp();
}
/**
* Test of main method, of class ComboBoxSample.
*/
@Test
public void testMain() {
//Delay so that we can see what's going on
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
}
window.textBox("textb").enterText("hi there");
window.textBox("textb").pressAndReleaseKeys(KeyEvent.VK_BACKSPACE);
window.comboBox().replaceText("Bean");
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_S);
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_DOWN);
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_DOWN);
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_DOWN);
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_ENTER);
}
}
断言J的测试文件:
package javapractice;
import com.sun.glass.events.KeyEvent;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* AssertJ imports.
*/
import org.assertj.swing.edt.FailOnThreadViolationRepaintManager;
import org.assertj.swing.edt.GuiActionRunner;
import org.assertj.swing.fixture.FrameFixture;
public class ComboBoxSampleTest {
private FrameFixture window;
private ComboBoxSample frame;
@BeforeClass
public static void setUpClass() {
FailOnThreadViolationRepaintManager.install();
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
frame = GuiActionRunner.execute(() -> new ComboBoxSample());
window = new FrameFixture(frame);
window.show();
}
@After
public void tearDown() {
window.cleanUp();
frame.cleanUp();
}
/**
* Test of main method, of class ComboBoxSample.
*/
@Test
public void testMain() {
//Delay so that we can see what's going on
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
}
window.textBox("textb").enterText("hi there");
window.textBox("textb").pressAndReleaseKeys(KeyEvent.VK_BACKSPACE);
window.comboBox().replaceText("Bean");
//the above line is the last one to execute
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_S);
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_DOWN);
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_DOWN);
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_DOWN);
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_ENTER);
}
}
这不是问题的答案,而是允许所需行为的解决方法。此问题可以通过为 comboBox() 调用 robot() 来缓解。
而不是
window.comboBox().pressAndReleaseKeys(KeyEvent.VK_S);
尝试做
window.comboBox().robot().pressAndReleaseKeys(KeyEvent.VK_S);