How to set up JUnit with WPILib?

We created a small WPILib project and tried to add unit testing with JUnit. So we just tried to instantiate the ExampleSubsystem in a test file. When we run gradlew build without the test, the build is successful. But when we add the test, it fails and we get the following error log (attached below).
The code is here. Specifically, the test file is here.
How do we fix this (specifically the wpiHaljni could not be loaded from path)?
Thanks!

Log:

Unexpected exception thrown.
org.gradle.internal.remote.internal.MessageIOException: Could not write '/127.0.0.1:65305'.
        at org.gradle.internal.remote.internal.inet.SocketConnection.flush(SocketConnection.java:140)
        at org.gradle.internal.remote.internal.hub.MessageHub$ConnectionDispatch.run(MessageHub.java:331)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.io.IOException: An existing connection was forcibly closed by the remote host
        at java.base/sun.nio.ch.SocketDispatcher.write0(Native Method)
        at java.base/sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
        at java.base/sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:113)
        at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:58)
        at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:50)
        at java.base/sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:466)
        at org.gradle.internal.remote.internal.inet.SocketConnection$SocketOutputStream.writeWithNonBlockingRetry(SocketConnection.java:279)
        at org.gradle.internal.remote.internal.inet.SocketConnection$SocketOutputStream.writeBufferToChannel(SocketConnection.java:267)
        at org.gradle.internal.remote.internal.inet.SocketConnection$SocketOutputStream.flush(SocketConnection.java:261)        at org.gradle.internal.remote.internal.inet.SocketConnection.flush(SocketConnection.java:138)
        ... 7 more

> Task :test FAILED

frc.robot.subsystems.ExampleSubsystemTest STANDARD_ERROR
    java.io.IOException: wpiHaljni could not be loaded from path or an embedded resource.
        attempted to load for platform /windows/x86-64/

        at edu.wpi.first.wpiutil.RuntimeLoader.loadLibrary(RuntimeLoader.java:78)
        at edu.wpi.first.hal.JNIWrapper.<clinit>(JNIWrapper.java:38)
        at edu.wpi.first.wpilibj2.command.CommandScheduler.<init>(CommandScheduler.java:92)
        at edu.wpi.first.wpilibj2.command.CommandScheduler.getInstance(CommandScheduler.java:51)
        at edu.wpi.first.wpilibj2.command.SubsystemBase.<init>(SubsystemBase.java:27)
        at frc.robot.subsystems.ExampleSubsystem.<init>(ExampleSubsystem.java:16)
        at frc.robot.subsystems.ExampleSubsystemTest.<init>(ExampleSubsystemTest.java:13)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217)
        at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
        at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
        at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
        at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:118)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
        at java.base/java.lang.Thread.run(Thread.java:834)

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> Process 'Gradle Test Executor 8' finished with non-zero exit value 1
  This problem might be caused by incorrect test process configuration.
  Please refer to the test execution section in the User Manual at https://docs.gradle.org/6.0.1/userguide/java_testing.html#sec:test_execution

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 6s
6 actionable tasks: 6 executed

This could be caused by a few things, but if not running from the wpilib installed jdk, this can be caused by missing the lastest c++ runtime. As a first thing, can you try installing the latest visual c++ redistributable for 64 bit and trying again? That will get the first easy thing out of the way.

https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads

1 Like

Would he also need to enable DesktopSupport to get the x86-64 wpiHaljni?

Nope. That flag does nothing in Java. It’s only there so I didn’t have to special case the code that changes it in vscode, and there for future use if needed.

check this out. i spent a bunch of time before build season getting JUnit tests to work:

1 Like

Thank you! That was the needed solution, we really did not use the WPILib installer.

How do you run the junit test from vscode?

We do not use Visual Studio Code but IntelliJ IDEA, so, unfortunately, I don’t have an answer. We’re using IntelliJ IDEA’s unit testing integration.
However, you can just run gradlew build as usual in the command line and it will run the tests too.

Thanks. I’ll start a new thread, rather than hijack this one.

gonna look at IDEAJ this summer, looks like gradlerio is getting more “not vscode” friendly.

I’m don’t think you have to wait until summer. The transition is pretty intuitive and you can learn all the really cool features in IntelliJ IDEA over time.

I agree it’s an easy transition (I use IDEAJ professionally), but I have gotten allergic to making changes to procedure in the middle of build season!

Wait - last time I tried, IntelliJ’s unit testing integration flatly did not work (it would attempt to run the code on a RoboRIO build instead of a sim build, and would crash with HAL errors), and the only option was to use the command line. Has this changed?

After we installed what @Thad_House recommended, it worked from the command line and IntelliJ, too. I’ll double-check for you tomorrow.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.