MockBukkit: unit testing Bukkit plugins against a mock server
MockBukkit is a mocking framework for Bukkit/PaperMC to allow the easy unit testing of Bukkit plugins.
At a glance
- What is it?
- MockBukkit provides a mock implementation of CraftBukkit that a test can drive directly, with mock plugins, players and worlds, published to Maven Central per Minecraft version. It suits plugin developers who want fast unit tests, with the catch that unimplemented parts of the API throw UnimplementedOperationException and quietly skip the test.
- Who is it for?
- Use MockBukkit if you maintain a Bukkit or PaperMC plugin and want unit tests that run in milliseconds without starting a server, and if you are willing to keep an eye on which parts of the API your code actually touches. Do not adopt it as a substitute for integration testing against a real server, since a mock only implements what the project has implemented, and treat a green build with skipped tests as a warning rather than a pass.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A mock CraftBukkit that the test drives
MockBukkit is a mocking framework for Bukkit and PaperMC that aims to provide a complete mock implementation of CraftBukkit that can be completely controlled from a unit test.
The problem it addresses is one that every Minecraft server plugin developer knows. Testing a plugin normally means starting a server, waiting for it to come up, and driving the plugin through the event and API surface that the server exposes. That is slow, it is stateful, and a failure halfway through leaves a broken world behind. A mock replaces the server with an object graph that the test owns, so a plugin can be loaded, a player can be simulated, an event can be fired, and the assertions can run inside a normal unit test.
The project is Java, MIT licensed, published to Maven Central, and documented at mockbukkit.org. The repository is not archived and the last push was on 2026-10-18.
What the mock covers is what makes it useful. The README lists mock plugins, mock players and mock worlds as the headline features, alongside a troubleshooting section for the most common failure, which is worth reading before you write your first test.
The scope is a mock, and the word complete in the README is doing some work. A mock implementation of a large server API is a large ongoing effort, so the practical question for any adopter is how much of the API your plugin actually uses.
Mock plugins, mock players, mock worlds
The three feature groups map onto the three things a plugin touches.
Mock plugins are the entry point. Your plugin is loaded into the mock rather than into a real server, and the mock exposes the plugin lifecycle so the test can enable, disable and trigger the plugin the way the server would. This is the piece that makes the rest possible, because without it there is nothing for a player to interact with.
Mock players are the event source. A test can create a player, give it inventory, permissions and a location, and then have that player perform actions, which produce the events your listeners are written against. Because the players are objects the test holds, assertions read as ordinary Java rather than as log scraping.
Mock worlds are the state. A test can create a world, place blocks, spawn entities and set the time of day, which covers the large class of plugin logic that reads or writes the world rather than responding to a player.
Between them, the three groups cover most of what a typical plugin does, which is why the framework is worth the dependency. The gaps are the interesting part, and they show up as an UnimplementedOperationException rather than as a silently wrong result, which is a better failure mode than a mock that returns nulls.
The version scheme and why the Paper version comes from a jar manifest
MockBukkit is versioned per Minecraft release, and the current artifact is mockbukkit-v26.3, published to Maven Central under the group id org.mockbukkit.mockbukkit. The default branch of the repository is minecraft/v26.3, and the branches list includes older lines such as v1.13-SNAPSHOT.
The Gradle setup in the README is unusual and worth understanding, because it explains a thing that would otherwise look like boilerplate. MockBukkit has to be compiled against a specific Paper API version, and the test project needs the same Paper API on the classpath. Rather than asking you to keep two version numbers in step by hand, the snippet resolves the mockbukkit jar from the test configuration, opens it, and reads the Paper-Version attribute out of its manifest:
def manifest = jarFile.manifest
def paperVersion = manifest.mainAttributes.getValue('Paper-Version')with a fallback to 1.21-R0.1-SNAPSHOT when the attribute is missing. The Maven instructions do the same thing with the groovy-maven-plugin, reading the manifest and setting a project property.
The result is a build where the Paper API version follows the MockBukkit version automatically, which is the only arrangement that stays correct when the project bumps to the next Minecraft release.
There is a versioning wrinkle the README calls out. The breaking changes intended for 3.0 were already made in 2.145.1, and due to an error that version was not properly tagged. So the jump from the 2.x line to the 3.x line contains no API change even though the numbers suggest it does.
Adding it to a Gradle build
The dependency setup is short once the version resolution is in place. Two repositories are needed, Maven Central for MockBukkit itself and the PaperMC repository for the Paper API:
repositories {
mavenCentral()
maven { url 'https://repo.papermc.io/repository/maven-public/' }
}
dependencies {
testImplementation 'org.mockbukkit.mockbukkit:mockbukkit-v26.3:${paperVersion}'
}It goes in as a testImplementation dependency, which is the right scope: the mock is a test tool and should never end up in the plugin jar.
The Maven equivalent adds the PaperMC repository in the same way and declares the dependency with a test scope, with a note that the MockBukkit dependency has to be placed above the dependency that provides Bukkit, so that the mock wins on the classpath.
For people who want the newest code or a specific commit, JitPack is offered as an alternative repository:
repositories {
maven { url 'https://jitpack.io' }
maven { url 'https://repo.papermc.io/repository/maven-public/' }
}
dependencies {
testImplementation 'com.github.MockBukkit:MockBukkit:v26.3-SNAPSHOT'
testImplementation 'io.papermc.paper:paper-api:${paperVersion}'
}Note that the JitPack coordinates differ from the Maven Central ones, and that with JitPack you also declare the Paper API explicitly, because the snapshot build does not carry the same manifest attribute.
The skipped test: UnimplementedOperationException
The troubleshooting section of the README has a single entry, and its title tells you what it is: my tests are being skipped, with an UnimplementedOperationException.
This is the characteristic failure of a mock framework, and it is worth understanding rather than working around. When your plugin calls a part of the Bukkit API that MockBukkit has not implemented, the mock throws an UnimplementedOperationException. If the test framework treats an exception of that type as a skip rather than a failure, the test is reported as skipped and the build stays green.
That is a genuinely dangerous default, because a suite can quietly stop testing anything. The tell is a run where the number of skipped tests grows while the number of executed tests falls.
The practical response is to treat skipped tests as work in progress rather than as passes. If your CI reports skips separately, and it fails on them, the problem surfaces immediately. Otherwise, adding an assertion that fails when a test is skipped is the cheapest way to keep the suite honest.
There is a second reason to care. A skipped test tells you the mock does not cover that area of the API, which is also a statement about the plugin: a plugin that only touches implemented API surface is one that is likely to be testable in isolation, and a plugin that reaches into unusual corners of the server API is the one that will need a real server to test properly.
Branches, backports and the cost of supporting old versions
The README is open about a limitation that most versioning schemes hide. The note about the v1.13-SNAPSHOT branch says that those branches will not be receiving patches actively, but any issues will be resolved and any pull requests on them will be accepted, and it gives the reason: back-porting every single patch on every branch is incredibly time-consuming and slows down the development of MockBukkit.
That is a candid trade. A plugin that still targets an old Minecraft version can use the matching MockBukkit branch, and will get fixes when someone sends them, but will not get them automatically. In practice this means the version of MockBukkit you depend on is tied to the version of Minecraft you support, and the two move at different speeds.
The branch layout follows from that. The default branch is minecraft/v26.3, one branch per Minecraft line, and the published artifact is named after that line, mockbukkit-v26.3. The Maven Central coordinates carry the same suffix, so the artifact you request tells you which Minecraft release it targets.
The release process is also unusual. The repository publishes no GitHub releases, and the distribution channel is Maven Central, with the badge in the README pointing at the current artifact and the Javadocs for it hosted on javadoc.io.
The other structural detail in the repository is the metaminer directory, alongside src, extra, config, the Gradle build files, a .sdkmanrc for the JDK version and a jitpack.yml for the JitPack builds. The project is built with Gradle in Kotlin DSL, with settings.gradle.kts and build.gradle.kts at the root, and it carries the usual quality integrations: Codecov for coverage, SonarCloud for code smells, bugs and maintainability, and a publish workflow.
Editorial conclusion
Use MockBukkit if you maintain a Bukkit or PaperMC plugin and want unit tests that run in milliseconds without starting a server, and if you are willing to keep an eye on which parts of the API your code actually touches. Do not adopt it as a substitute for integration testing against a real server, since a mock only implements what the project has implemented, and treat a green build with skipped tests as a warning rather than a pass. Before you start, pick the MockBukkit artifact that matches your target Minecraft version, read the troubleshooting note about UnimplementedOperationException, and note that the repository publishes no GitHub releases while the current artifact is mockbukkit-v26.3, with the last push on 2026-10-18.
Frequently asked questions
What is MockBukkit and what does it do?
MockBukkit is a mocking framework for Bukkit and PaperMC that provides a mock implementation of CraftBukkit which can be completely controlled from a unit test. It offers mock plugins, mock players and mock worlds so plugin logic can be tested without starting a server.
How do I add MockBukkit to a Gradle project?
Add mavenCentral() and the PaperMC repository, then declare testImplementation 'org.mockbukkit.mockbukkit:mockbukkit-v26.3:${paperVersion}'. The paperVersion value is read from the Paper-Version attribute of the mockbukkit jar manifest so that the Paper API version follows the MockBukkit version automatically.
Why are my MockBukkit tests being skipped?
The README lists UnimplementedOperationException as the cause, which happens when your plugin calls a part of the Bukkit API that MockBukkit has not implemented and the test framework treats that exception as a skip. Because a green build can then contain many skipped tests, it is worth failing the run on skips rather than ignoring them.
Where is MockBukkit published and how are versions named?
The artifacts are published to Maven Central under the group id org.mockbukkit.mockbukkit, with the artifact named after the Minecraft line, currently mockbukkit-v26.3, and the repository publishes no GitHub releases. Older lines such as v1.13-SNAPSHOT exist as branches that are not patched automatically.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mockbukkit-mockbukkit)Was this useful?