我完全陷入了java测试;关于通过测试方法发送字符' a'到JFrame组件的JTextField。
JFrame类实现KeyListener接口,因此会覆盖KeyPressed,KeyTyped和KeyReleased。与此同时,我将JTextField的所有keypressed转移到JFrame;我在JFrame构造函数中有:
JTextField txf_version = new JTextField();
txf_version.addKeyListener(this);
我想测试这种行为,然后模拟JTextField中字符类型的操作。
我所有的尝试都失败了;我尝试使用java.awt.Robot类,如下所示:hava a look at this other post in stack overflow,但我得到一个奇怪的行为:调用
robot.keyPress(KeyEvent.VK_A);
直接在IDE中显示字符,而不是在虚拟JFrame中显示!尝试使用requestFocus()或requestFocusInWindow()无效。
我也尝试过使用KeyEvents:
KeyEvent key = new KeyEvent(bookWindow.txf_version, KeyEvent.KEY_PRESSED, System
.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'a');
bookWindow.txf_version.dispatchEvent(key);
但同样,textfield的text属性也没有改变......
这是我现在的方法:
@Test
void testBtnSaveChangesBecomesRedWhenVersionChanged() throws AWTException,
InterruptedException, NoSuchFieldException, IllegalAccessException {
initTest();
KeyEvent key = new KeyEvent(bookWindow.txf_version, KeyEvent.KEY_PRESSED, System
.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'a');
bookWindow.txf_version.dispatchEvent(key);
System.out.println("dans txf_version : " + bookWindow.txf_version.getText
());
assertEquals(Color.RED, bookWindow.getBtnSaveChangesForegroundColor());
}
我可以通过在JFrame的子类中编写main()方法来查看实际行为,但我认为知道如何模拟swing组件测试的键是很有用的。
谢谢
编辑: 我根据AJNeufeld的回答更改了我的测试代码,但它仍然无法正常工作。这是我的测试代码:
@Test
void testBtnSaveChangesBecomesRedWhenVersionChanged() throws AWTException,
InterruptedException, NoSuchFieldException, IllegalAccessException,
InvocationTargetException {
//bookEditor2 & bookWindow
SwingUtilities.invokeAndWait(() -> {
bookWindow = new BookWindow();
VectorPerso two = new VectorPerso();
two.add(le_livre_de_la_jungle);
two.add(elogeMaths);
bookWindow.setTableDatas(two);
bookWindow.table.setRowSelectionInterval(1, 1);
bookWindow.txf_version.requestFocusInWindow();
KeyEvent key = new KeyEvent(bookWindow.txf_version, KeyEvent.KEY_TYPED, System
.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'a');
bookWindow.txf_version.dispatchEvent(key);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("dans txf_version : " + bookWindow.txf_version.getText
());
assertEquals(Color.RED, bookWindow.getBtnSaveChangesForegroundColor());
});
}
plintln行在控制台中生成一个文本:" dans txf_version:0",表示密钥未发送到txf_version。
编辑2:
新尝试:
@Test
void testBtnSaveChangesBecomesRedWhenVersionChanged() throws AWTException,
InterruptedException, NoSuchFieldException, IllegalAccessException,
InvocationTargetException {
//bookEditor2 & bookWindow
SwingUtilities.invokeAndWait(() -> {
bookWindow = new BookWindow();
VectorPerso two = new VectorPerso();
two.add(le_livre_de_la_jungle);
two.add(elogeMaths);
bookWindow.setTableDatas(two);
bookWindow.table.setRowSelectionInterval(1, 1);
bookWindow.txf_version.requestFocusInWindow();
KeyEvent key = new KeyEvent(bookWindow.txf_version, KeyEvent.KEY_TYPED, System
.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'a');
bookWindow.txf_version.dispatchEvent(key);
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeAndWait(() -> {
System.out.println("dans txf_version : " + bookWindow.txf_version.getText
());
assertEquals(Color.RED, bookWindow.getBtnSaveChangesForegroundColor());
});
}
答案 0 :(得分:1)
我认为你做了一些错事,但没有一个完整的例子,很难说清楚。
首先,JTextField
并不真正关注KEY_PRESSED
事件。它关注KEY_TYPED
事件。
其次,Swing处理Event Dispatching Thread(EDT)上的事件,它不一定是JUnit将要运行的线程。当你不在美国东部时,你真的不应该改变事情。我不确定eventDispatch()
是否切换到EDT。它可能。但它也可能使用invokeLater()
来执行此操作,在这种情况下,执行会立即传递给assertEquals()
,但失败,因为事件处理尚未发生。
这是一个最小的,完整的,可验证的示例,它显示了一个发送的按键,它改变了按钮的颜色,还有一个JUnit测试用例,用于检查和传递:
首先,测试中的代码:
public class SwingUnitTesting extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(SwingUnitTesting::new);
}
JTextField tf = new JTextField();
JButton btn = new JButton("Test Button");
SwingUnitTesting() {
add(tf, BorderLayout.PAGE_END);
add(btn, BorderLayout.PAGE_START);
tf.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
btn.setForeground(Color.RED);
}
});
setSize(200, 80);
setLocationByPlatform(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
}
}
单元测试:
public class SwingUnitTestingTest {
SwingUnitTesting sut;
@Before
public void setUp() throws Exception {
SwingUtilities.invokeAndWait(() -> {
sut = new SwingUnitTesting();
});
}
@Test
public void btnNotRedBeforeKeypress() throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(() -> {
assertNotEquals(Color.RED, sut.btn.getForeground());
});
}
@Test
public void btnRedAfterKeypress() throws InvocationTargetException, InterruptedException {
SwingUtilities.invokeAndWait(() -> {
sut.tf.requestFocusInWindow();
sut.tf.dispatchEvent(new KeyEvent(sut.tf,
KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0,
KeyEvent.VK_UNDEFINED, 'A'));
assertEquals(Color.RED, sut.btn.getForeground());
});
}
}
您可以使用一些JUnit @Rule
技巧或自定义运行器在运行挥杆测试时自动更改为EDT。
<强>更新强>:
我很好奇,并试图找到一个现有的@Rule
,它将@Before
,@Test
和@After
代码放到了EDT上,但是我的Google-fu我失败了;
我知道我以前见过它,但我找不到它。
最后,我创建了自己的:
public class EDTRule implements TestRule {
@Override
public Statement apply(Statement stmt, Description dscr) {
return new Statement() {
private Throwable ex;
@Override
public void evaluate() throws Throwable {
SwingUtilities.invokeAndWait(() -> {
try {
stmt.evaluate();
} catch (Throwable t) {
ex = t;
}
});
if (ex != null) {
throw ex;
}
}
};
}
}
使用此规则,JUnit测试变得更简单:
public class SwingUnitTestingTest {
@Rule
public TestRule edt = new EDTRule();
SwingUnitTesting sut;
@Before
public void setUp() throws Exception {
sut = new SwingUnitTesting();
}
@Test
public void btnNotRedBeforeKeypress() {
assertNotEquals(Color.RED, sut.btn.getForeground());
}
@Test
public void btnRedAfterKeypress() {
sut.tf.requestFocusInWindow();
sut.tf.dispatchEvent(
new KeyEvent(sut.tf, KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'A'));
assertEquals(Color.RED, sut.btn.getForeground());
}
}
使用jdk1.8.0_121
在MacOS上测试答案 1 :(得分:0)
1)我们仍然在寻找使用SWING的解决方案(但在这种情况下,我没有任何经验和任何想法如何帮助你)。
2)使用Sikulli java框架测试桌面应用程序。您可以添加dependency然后
并撰写动作,移动,点击或实际需要的内容。 非常简单,看起来像
按钮按钮=新按钮(&#34;测试文件夹/ pic1.jpg&#34;);
button.click();
运行后,您将看到,光标移动按钮,然后单击它。
有关更多详细信息,请在Web上查找有关Sikulli + Java的示例。
答案 2 :(得分:0)
最近,我不得不测试一个自定义的KeyAdapter,并创建了一个自定义的JTextField来分发键事件。下面是我使用的一部分代码:
implementation 'mysql:mysql-connector-java:5.1.45'