WatchWolf

MockBukkit VS WatchWolf

MockBukkit is a framework that makes the unit testing of Bukkit plugins a whole lot easier. WatchWolf is an integration testing environment for Spigot plugins.

Start time

~50ms >2 min

JavaPlugin changes

Barely nothing
Just by providing an extra constructor (ref) you're good to go.
Nothing
WatchWolf uses the already compiled plugin, so you don't have to change anything.

Installation

Maven dependency Maven dependency + Docker + WatchWolf
To run the tests you'll need a Maven dependency, but as you have to start an actual server you'll also need a WatchWolf instance.

Additional configutation

Nothing Config file
You'll have to specify the server types and versions where you want to test your plugin. Also, you'll have to specify how many users you need for the tests. (ref).

Test comparison


I've provided a basic plugin example here, the idea is that you can run a command to undo the last block you've placed.

@Test
public void restoreTheLastBrokenBlock() throws IOException {
    /* decide where/who will interact with the event */
    PlayerMock player = server.addPlayer();
    Location whereToPlaceTheBlock = player.getLocation().add(1,0,0); // block next to the user
    Material whatBlockWillBePlaced = Material.DIRT;
    World world = server.getWorld("world");

    /* prepare the environment (make sure the player can place the block there) */
    world.setBlockData(whereToPlaceTheBlock, server.createBlockData(Material.AIR));

    /* prepare the client (give him the block to place) */
    // TODO MockBukkit's clients doesn't need the block to place it

    /* start the test */
    player.simulateBlockPlace(whatBlockWillBePlaced, whereToPlaceTheBlock); // place the block
    player.performCommand("ctrl-z"); // undo

    // we expect air in the place we've put the block
    assertEquals(Material.AIR, world.getBlockAt(whereToPlaceTheBlock).getBlockData().getMaterial());
    assertEquals(1, PlacedBlockCtrlZShould.getItemAmounts(player.getInventory().getContents())
            .get(whatBlockWillBePlaced)); // we expect 1 dirt block back
}
            

@ParameterizedTest
@ArgumentsSource(PlacedBlockCtrlZShould.class)
public void restoreTheLastBrokenBlock(TesterConnector connector) throws IOException {
    /* decide where/who will interact with the event */
    String client = connector.getClients()[0];
    ExtendedClientPetition clientConnector = connector.getClientPetition(client);
    Position whereToPlaceTheBlock = clientConnector.getPosition().add(1,0,0); // block next to the user
    Block whatBlockWillBePlaced = Blocks.DIRT;

    /* prepare the environment (make sure the player can place the block there) */
    connector.server.setBlock(whereToPlaceTheBlock, Blocks.AIR);

    /* prepare the client (give him the block to place) */
    Item placedBlockItem = new Item(whatBlockWillBePlaced.getItemType());
    connector.server.giveItem(client, placedBlockItem);

    /* start the test */
    clientConnector.setBlock(whatBlockWillBePlaced, whereToPlaceTheBlock); // place the block
    clientConnector.runCommand("ctrl-z"); // undo

    // we expect air in the place we've put the block
    assertEquals(Blocks.AIR, connector.server.getBlock(whereToPlaceTheBlock));
    assertEquals(1, getItemAmounts(clientConnector.getInventory().getItems())
            .get(whatBlockWillBePlaced.getItemType())); // we expect 1 dirt block back
}
            

Conclusions

Due to all the methods available and its speed, MockBukkit is perfect to quickly test your newly added features. By actually starting a server you can test your plugin before releasing it, so you make sure it works in all the versions and server types. Also, in a future version you'll be able to test database-dependent plugins.