You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

libGDX按键输入单元测试:使用Robot模拟左箭头按键时Gdx.input为空的初始化方法

如何在libGDX单元测试中初始化Gdx.input以避免空指针异常?

我尝试通过Robot类模拟用户按下左箭头按键,以此对libGDX框架的isKeyPressed方法进行单元测试,但执行测试时持续出现错误提示:Cannot invoke "com.badlogic.gdx.Input.isKeyPressed(int)" because "com.badlogic.gdx.Gdx.input" is null。请问应如何正确初始化Gdx.input,使其不为空?我的测试代码如下:

class GameScreenTest {
    @Test
    void movementLeft() throws AWTException {
        int x = 10;
        Robot robot = new Robot();
        int keyCodeLeft = KeyEvent.VK_LEFT;
        robot.keyPress(keyCodeLeft);
        robot.keyRelease(keyCodeLeft);
        if(Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
            x -= 5;
        }
        assertEquals(5, x);
    }
}

先给你理清问题根源:你用的Robot是Java AWT的系统级输入工具,它模拟的是操作系统层面的按键事件,但libGDX的Gdx.input是框架自己的输入处理接口——在单元测试环境里,libGDX的核心组件(包括Gdx.input)默认不会被初始化,所以会报空指针;而且就算初始化了,Robot的事件也不会被Gdx.input捕获,因为两者的事件通道完全独立。

下面是两种可行的解决办法:

方法一:用libGDX官方测试扩展(推荐)

libGDX专门提供了无头后端(headless backend)和测试支持库,能帮你完整初始化框架组件,包括Gdx.input。

步骤1:添加测试依赖

如果用Gradle,在build.gradle的测试依赖里加上:

testImplementation "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion"
testImplementation "com.badlogic.gdx:gdx-test:$gdxVersion"

把$gdxVersion换成你项目里用的libGDX版本号。

步骤2:编写测试代码

在测试类里初始化无头应用,然后手动模拟按键状态:

import com.badlogic.gdx.backends.headless.HeadlessApplication;
import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Gdx;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class GameScreenTest {

    private HeadlessApplication headlessApp;

    @BeforeEach
    void setUp() {
        // 初始化无头应用,这会自动初始化Gdx.input
        HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
        headlessApp = new HeadlessApplication(new InputAdapter() {}, config);
    }

    @AfterEach
    void tearDown() {
        // 测试结束后关闭应用,避免资源泄漏
        headlessApp.exit();
    }

    @Test
    void movementLeft() {
        int x = 10;
        
        // 手动设置LEFT按键为按下状态
        ((Input) Gdx.input).setKeyPressed(Input.Keys.LEFT, true);
        
        if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
            x -= 5;
        }
        
        assertEquals(5, x);
        
        // 记得模拟按键释放,避免影响后续测试
        ((Input) Gdx.input).setKeyPressed(Input.Keys.LEFT, false);
    }
}

方法二:用Mockito手动Mock Input对象

如果不想引入额外的libGDX测试依赖,可以用Mockito创建一个Input的模拟对象,直接赋值给Gdx.input。

步骤1:添加Mockito依赖

Gradle里加:

testImplementation "org.mockito:mockito-core:4.+"

步骤2:编写测试代码

import com.badlogic.gdx.Input;
import com.badlogic.gdx.Gdx;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class GameScreenTest {

    @Test
    void movementLeft() {
        // 创建Input的Mock对象
        Input mockInput = mock(Input.class);
        // 设定当调用isKeyPressed(LEFT)时返回true
        when(mockInput.isKeyPressed(Input.Keys.LEFT)).thenReturn(true);
        
        // 把Mock对象赋值给Gdx.input
        Gdx.input = mockInput;
        
        int x = 10;
        if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
            x -= 5;
        }
        
        assertEquals(5, x);
        
        // 测试结束后清理,避免影响其他测试用例
        Gdx.input = null;
    }
}

内容的提问来源于stack exchange,提问作者s16

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 16:42:28