在 JUnit 测试中模拟按键

2023-12-19

我完全陷入了java测试;它是通过测试方法将字符“a”发送到 JFrame 组件的 JTextField。

JFrame 类实现 KeyListener 接口,因此覆盖 KeyPressed、KeyTyped 和 KeyReleased。与此同时,我将 JTextField 的所有按键传输到 JFrame;在 JFrame 构造函数内我有:

JTextField txf_version = new JTextField();
txf_version.addKeyListener(this);

我想测试此行为,然后模拟在 JTextField 中键入字符的操作。

我所有的尝试都失败了;我尝试使用 java.awt.Robot 类,如下所示:看看堆栈溢出中的另一篇文章 https://stackoverflow.com/questions/7745959/how-to-simulate-keyboard-presses-in-java,但我得到了一个奇怪的行为:打电话

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);

但文本字段的文本属性再次没有改变......

这是我现在的方法:

@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。

EDIT 2:

new try:

@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());
    });


  }

我认为你做错了几件事,但没有完整的例子,很难说清楚。

首先,JTextField并不真正关心KEY_PRESSED事件。它涉及的是KEY_TYPED events.

其次,Swing 在事件调度线程 (EDT) 上处理事件,该线程不一定是 JUnit 将要运行的线程。当你不在 EDT 时,你真的不应该改变事情。我不确定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。


Update:

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

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());
    }
}

在MacOS上测试,使用jdk1.8.0_121

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 JUnit 测试中模拟按键 的相关文章

  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • Mockito when().thenReturn 不必要地调用该方法

    我正在研究继承的代码 我编写了一个应该捕获 NullPointerException 的测试 因为它试图从 null 对象调用方法 Test expected NullPointerException class public void c
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • 如何为俚语和表情符号构建正则表达式 (regex)

    我需要构建一个正则表达式来匹配俚语 即 lol lmao imo 等 和表情符号 即 P 等 我按照以下示例进行操作http www coderanch com t 497238 java java Regular Expression D
  • 如何将 pfx 文件转换为 jks,然后通过使用 wsdl 生成的类来使用它来签署传出的肥皂请求

    我正在寻找一个代码示例 该示例演示如何使用 PFX 证书通过 SSL 访问安全 Web 服务 我有证书及其密码 我首先使用下面提到的命令创建一个 KeyStore 实例 keytool importkeystore destkeystore
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口

随机推荐

  • 如何在 Android 应用程序中创建数据库?

    我正在尝试在我的 Android 应用程序中使用 SQLite 我创建了这样的辅助类 public class EventoSQLHelper Configura o da base nome e vers o private static
  • searchable_dropdown 不适用于类列表

    我使用 searchable dropdown 1 1 0 包实现了一个颤振下拉菜单 我用我的班级列表进行了测试 发现搜索文本字段框不适用于我的班级列表 我希望当我在列表中的字符串 整数中搜索值时 我的下拉搜索框能够正常工作 例如 我希望当
  • 未知的正则化器:tensorflowjs 中的 L2

    我已经使用 model 在 python 中训练了一个模型 reg 0 000001 model Sequential model add Dense 24 activation tanh name input dense input sh
  • SQL:给定行之前和之后的行数

    问题是我们要获取给定行 例如由主键标识 之前和之后的总行数 我尝试过在 T SQL MSSQL 2008 中执行以下操作 它给出了正确的结果 但我不知道这是否是最好的方法 WITH cte before AS SELECT ROW NUMB
  • 是否可以在 Spring 中以基于表单的身份验证发送更多数据?

    我对这个比较陌生Spring框架 http en wikipedia org wiki Spring Framework和春季安全 我使用了自定义身份验证方案 HTML
  • 将大型 3gp 文件转换为字节数组

    我正在尝试将大型 3gp 文件 gt 25mb 转换为字节数组 但它给出了内存不足异常 我能够将小于 25 mb 的 3gp 文件转换为字节数组 文件文件1 新文件 Environment getExternalStorageDirecto
  • 如何最大限度地提高 C# 中大数组上按元素运算的性能

    该操作是将数组的每个第 i 个元素 称为 A 与相同大小的矩阵 B 的第 i 个元素相乘 并用获得的值更新 A 的相同第 i 个元素 在算术公式中 A i A i B i 0 在多核环境中优化此操作的最佳方法是什么 这是我当前的代码 var
  • 提取 ARIMA 规范

    从 auto arima 打印拟合模型对象包括一行 例如 带有漂移的 ARIMA 2 1 0 这将是一个很好的项目 可以包含在说明拟合模型的 sweave 或其他 输出中 是否可以将该行提取为块 此时 我所做的最好的事情是从 arma 组件
  • 如何从asp.net中的url中删除页面名称?

    来自以下网址 http www mywebsite com default aspx 我想删除default aspx 这样网址将如下所示 http www mywebsite com 我需要一种快速而干净的方法来执行此操作 并且我只需要使
  • 在单独的构建过程中签入文件后,我可以绕过门控签入构建吗? 2010年TFS

    我为解决方案设置了 2 个构建定义 1 个是每晚触发的夜间构建 另一个是门控签入构建 当开发人员尝试将新更改签入源代码管理时将触发 每晚构建使用自定义模板 该模板使用稍微修改过的方法来增加程序集版本埃瓦尔德 霍夫曼法 http www ew
  • 一夜不活动后出现一般网络错误

    一段时间以来 我们的旗舰应用程序一直出现神秘错误 错误消息是通用的 DBNETLIB ConnectionWrite send 一般网络错误 检查您的网络文档 通过让应用程序在晚上打开并在早上恢复工作 可以可靠地重现这一点 由于它是后端服务
  • Rails 2.3 和 rspec-rails 兼容性

    什么版本的rspec railsgem 仍然与 Rails 2 3 分支兼容 特别是 2 3 14 我试过了2 1 0 但这也适用于 Rails gt 3 0 我应该注意的任何其他依赖项或版本限制吗 Thanks 版本 1 3 4 是 Ra
  • mysql + 导入列标题中有空格的文件 + 如何处理

    我有一个 csv 文件 我想将其导入到 mysql 中 我正在慢慢地做到这一点 我正在尝试使用加载数据文件 https stackoverflow com a 20895203 2392358但首先我必须创建表格 这就是我的问题所在 我尝试
  • Android:与 Android 设备进行 RS232 串行通信

    我有一个MR400s 出租车计价器 http www taxiworld co uk london taximeter rentals硬件 我想使用RS232电缆与这个出租车计价器进行通信 并且我已经在Windows中实现了这种连接和通信
  • 程序结束后出现分段错误

    我正在做一项家庭作业 而且我对 C 还比较陌生 我必须为整数数组创建一个初始值设定项 我的教授给我的声明是 typedef int set t Can t be altered void init set t thing int N Can
  • DNS-SD:使用“mdnsjava”的经验? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我现在正在实施 DNS DS 库 mdnsjava https code google com p mdnsjava 进入我的Andr
  • jquery创建二维数组

    编辑 看来我对我想要完成的事情有点困惑 对于那些花时间解释这一点的人 谢谢 我正在尝试在 Jquery Javascript 中创建一个二维数组 我已经进行了大量的搜索 测试和更多搜索 但我无法找到对我来说真正有意义的解决方案 这已经是漫长
  • python请求中的Http重定向代码3XX

    我正在尝试捕获重定向 url 的 http 状态代码 3XX 302 但我无法获取它 因为它给出了 200 状态代码 这是代码 import requests r requests get http goo gl NZek5 print r
  • IdentityServer4 如何在登录后重定向到上一个 url 页面而不在 IdP 注册所有路由

    按照建议 我会在 IdP 上注册授权回调 url redirect url 它可以工作 但是 如果使用 MVC 应用程序的客户端尝试访问未经授权的页面 将会被重定向到 idsrv 登录页面 该怎么办 redirect url 始终是配置的
  • 在 JUnit 测试中模拟按键

    我完全陷入了java测试 它是通过测试方法将字符 a 发送到 JFrame 组件的 JTextField JFrame 类实现 KeyListener 接口 因此覆盖 KeyPressed KeyTyped 和 KeyReleased 与此