question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Writing Java tests for Fabric

See original GitHub issue

While the gametest framework is a fantastic utility for testing Minecraft mods, there’s often times when it’s desirable to write unit tests more isolated integration tests[^1] instead. However, as mixins aren’t applied inside a test environment, there’s only so much you can do before hitting LinkageError or other fun runtime issues!

Several mods have solved this by injecting Fabric loader as part of the test initialisation process (for example multiconnect and AE2). However, given this is quite an involved process (and is quite heavily tied to Fabric Loader internals), it feels like it would be good to have an official solution instead.

This obviously isn’t something Loom can solve in isolation (it would, I assume require some changes to Fabric Loader and/or DLI), but given it’s dev-tooling related, this seemed the best place.


This is the current solution I’m using. It hooks into the test lifecycle early on using JUnit’s automatic extension registration[^2], then installs a Java agent, acquiring an Instrumentation interface, which is then used for bytecode rewriting. To be clear, this isn’t good code, but hopefully shows that the underlying principle is viable!

To build something actually usable, I’d probably propose the following changes:

  • Add a new launcher class to Fabric Loader which loads mods and installs a ClassFileTransformer into a provided Instrumentation, but does not actually launch the game.

  • Define a JUnit extension somewhere (in DLI would sorta make sense, but could be a new project), which installs a Java agent and sets up Fabric Loader.

    The pain point here is that, unlike DLI, the extension shouldn’t rely on any system properties or arguments (as those won’t be present when running tests from an IDE). Short of hard-coding .gradle/loom-cache/launch.cfg into the extension, I’m not sure of a good way to detect the additional launch properties needed.

  • Add some method to Loom (loom.enableTestSupport()) which adds the test extension to the test runtime classpath.

I’m happy to take a look at implementing this, just wanted to check whether this was desirable and/or sensible.

[^1]: Player objects me calling these unit tests. More precisely, I want to write smaller-scale tests which only depend on a small subset of Minecraft’s functionality, and so don’t require spinning up a server. [^2]: This does require setting a system property, which is annoying. There’s probably other ways to nastily load early on, such as defining a TestEngine,

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:5
  • Comments:11 (8 by maintainers)

github_iconTop GitHub Comments

4reactions
SquidDevcommented, Nov 28, 2022

Oh, that’s fairly easy to do already - just add dependencies { testImplementation(sourceSets.client.output) } to your Gradle script. But possibly should be adding that to Loom too.

0reactions
SquidDevcommented, Dec 9, 2022

Yep, that’s pretty much what I did in CC:T (I use ClassInjector.UsingReflection rather than UsingInstrumentation). It’s definitely workable, just feels sufficiently ugly I wouldn’t want to build an “official” solution on top of it :p.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Has anyone created unit test cases for fabric pre and post ...
We have written few pre and post processors in java and want to write unit test cases ... Quantum Fabric; Post Processors; Unit...
Read more >
fabric-chaincode-java/MyAssetContractTest.java at main
Hyperledger Fabric Contract and Chaincode implementation for Java ... import org.junit.jupiter.api.Nested;. import org.junit.jupiter.api.Test;.
Read more >
Setting up a mod development environment
Usually latest Gradle supports the recommended Java version 17. If you're developing mods for old version Minecraft, besides changing gradle.
Read more >
Test Driven Development for Java using JUnit | Quick Guide
JUnit is a unit testing framework designed for Java programming language. Since unit tests are the smallest elements in the test automation ...
Read more >
java - Checking the results of a Factory in a unit test
I implemented a factory that creates the appropriate object and returns the interface. I am writing a unit test for the factory. All...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found