首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在JUnit测试中模拟按键

在JUnit测试中模拟按键
EN

Stack Overflow用户
提问于 2017-11-16 18:25:23
回答 3查看 3.6K关注 0票数 2

我完全陷入了java测试中;这是关于通过测试方法将字符'a‘发送给JTextField的JFrame组件。

JFrame类实现KeyListener接口,因此重写KeyPressed、KeyTyped和KeyReleased。同时,我将JTextField的所有按键传递给JFrame;在JFrame构造函数中,我有:

代码语言:javascript
运行
复制
JTextField txf_version = new JTextField();
txf_version.addKeyListener(this);

我想测试这个行为,然后在JTextField中模拟一个字符的动作。

所有的尝试都失败了;我尝试了java.awt.Robot类,比如:看看堆栈溢出中的另一篇文章,但是我得到了一个奇怪的行为:调用

代码语言:javascript
运行
复制
robot.keyPress(KeyEvent.VK_A);

直接在IDE中显示字符,而不是在虚拟JFrame中显示!尝试使用requestFocus()或requestFocusInWindow()是无效的。

我还尝试过使用KeyEvents:

代码语言:javascript
运行
复制
KeyEvent key = new KeyEvent(bookWindow.txf_version, KeyEvent.KEY_PRESSED, System
        .currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, 'a');
bookWindow.txf_version.dispatchEvent(key);

但是textfield的text属性也没有被更改.

下面是我现在的方法:

代码语言:javascript
运行
复制
@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的答案更改了测试代码,但仍然无法工作。这是我的测试代码:

代码语言:javascript
运行
复制
@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:

新尝试:

代码语言:javascript
运行
复制
@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());
    });


  }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-11-17 02:07:14

我认为你做错了几件事,但如果没有一个完整的例子,就很难说了。

首先,JTextField并不真正关心KEY_PRESSED事件。它与KEY_TYPED事件有关。

其次,Swing处理事件分派线程(EDT)上的事件,这不一定是JUnit将要运行的线程。当你不在美国东部时间的时候,你真的不应该改变事情。我不确定eventDispatch()是否会切换到EDT。有可能。但是它也可能使用invokeLater()执行,在这种情况下,执行会立即传递给assertEquals(),这会失败,因为事件处理还没有发生。

下面是一个最小的、完整的、可验证的示例,它显示了发送的键(它改变了按钮的颜色)和一个检查它并通过的JUnit测试用例:

首先,正在测试的代码:

代码语言:javascript
运行
复制
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);
    }
}

单元测试:

代码语言:javascript
运行
复制
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());
        });
    }
}

在运行swing测试时,您可能可以使用一些JUnit @Rule技巧或自定义运行程序来自动更改为EDT。

更新

我很好奇,并试图找到一个现有的@Rule,它将@Before@Test@After代码放在EDT上,但我的Google失败了;我知道我以前见过它,但我找不到它。最后,我创造了我自己的:

代码语言:javascript
运行
复制
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测试变得更简单了:

代码语言:javascript
运行
复制
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());
    }
}

在MacOS上使用jdk1.8.0_121进行测试

票数 1
EN

Stack Overflow用户

发布于 2017-11-16 21:23:30

哟,我猜你有两个选择

( 1)仍然需要使用SWING找到解决方案(但在这种情况下,我没有经验,也没有任何想法来帮助您)。

2)使用Sikulli java框架对桌面应用程序进行测试。然后可以添加依赖性

  • 制作UI元素的屏幕截图,并使用sikuli + JUnit将它们放到应用程序的测试数据文件夹中
  • 编写简单的测试,为按钮的图片设置路径(例如)
  • 写动作,移动,点击或者你真正需要的东西。很简单,看起来就像 按钮=新按钮(“test-文件夹/pic1.jpg”); button.click();

运行后,您将看到,您的光标是移动按钮,并点击它。

有关更多细节,请在web中找到关于Sikulli + Java的示例。

票数 0
EN

Stack Overflow用户

发布于 2019-03-01 18:46:54

最近,我不得不测试一个定制的KeyAdapter,并创建了一个定制的JTextField来分派关键事件。我使用的一段代码如下:

代码语言:javascript
运行
复制
public class ProcessKeyOnTextFieldTest {

    @Test
    public void pressKeyTest() throws Exception {
        JTextFieldWithTypedKeySupport textField = new JTextFieldWithTypedKeySupport();

        textField.pressKey('a');
        textField.pressKey('b');

        assertEquals("ab", textField.getText());
    }

    class JTextFieldWithTypedKeySupport extends JTextField {

        int timestamp;

        void pressKey(char key) throws InvocationTargetException, InterruptedException {
            SwingUtilities.invokeAndWait(() -> super.processKeyEvent(createEvent(key)));
        }

        KeyEvent createEvent(char keyChar) {
            return new KeyEvent(this, KeyEvent.KEY_TYPED, timestamp++, 0, KeyEvent.VK_UNDEFINED, keyChar);
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47336703

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档