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
相关产品推荐
相关产品推荐

