16.2. Testing Cluster

Hazelcast allows you to create more than one member on the same JVM. Each member is called HazelcastInstance and each will have its own configuration, socket and threads, so you can treat them as totally separate members. This enables us to write and run cluster unit tests on single JVM. As you can use this feature for creating separate members different applications running on the same JVM (imagine running multiple webapps on the same JVM), you can also use this feature for testing Hazelcast cluster.

Let's say you want to test if two members have the same size of a map.

   @Test
    public void testTwoMemberMapSizes() {
        // start the first member
        HazelcastInstance h1 = Hazelcast.newHazelcastInstance(null);
        // get the map and put 1000 entries
        Map map1 = h1.getMap("testmap");
        for (int i = 0; i < 1000; i++) {
            map1.put(i, "value" + i);
        }
        // check the map size
        assertEquals(1000, map1.size());
        // start the second member
        HazelcastInstance h2 = Hazelcast.newHazelcastInstance(null);
        // get the same map from the second member
        Map map2 = h2.getMap("testmap");
        // check the size of map2
        assertEquals(1000, map2.size());
        // check the size of map1 again
        assertEquals(1000, map1.size());
    }

In the test above, everything happened in the same thread. When developing multi-threaded test, coordination of the thread executions has to be carefully handled. Usage of CountDownLatch for thread coordination is highly recommended. You can certainly use other things. Here is an example where we need to listen for messages and make sure that we got these messages:

   @Test
    public void testTopic() {
        // start two member cluster
        HazelcastInstance h1 = Hazelcast.newHazelcastInstance(null);
        HazelcastInstance h2 = Hazelcast.newHazelcastInstance(null);
        String topicName = "TestMessages";
        // get a topic from the first member and add a messageListener
        ITopic<String> topic1 = h1.getTopic(topicName);
        final CountDownLatch latch1 = new CountDownLatch(1);
        topic1.addMessageListener(new MessageListener() {
            public void onMessage(Object msg) {
                assertEquals("Test1", msg);
                latch1.countDown();
            }
        });
        // get a topic from the second member and add a messageListener
        ITopic<String> topic2 = h2.getTopic(topicName);
        final CountDownLatch latch2 = new CountDownLatch(2);
        topic2.addMessageListener(new MessageListener() {
            public void onMessage(Object msg) {
                assertEquals("Test1", msg);
                latch2.countDown();
            }
        });
        // publish the first message, both should receive this
        topic1.publish("Test1");
        // shutdown the first member
        h1.shutdown();
        // publish the second message, second member's topic should receive this
        topic2.publish("Test1");
        try {
            // assert that the first member's topic got the message
            assertTrue(latch1.await(5, TimeUnit.SECONDS));
            // assert that the second members' topic got two messages
            assertTrue(latch2.await(5, TimeUnit.SECONDS));
        } catch (InterruptedException ignored) {
        }
    }

You can surely start Hazelcast members with different configuration. Let's say we want to test if Hazelcast SuperClient can shutdown fine.

   @Test(timeout = 60000)
    public void shutdownSuperClient() {
        // first config for normal cluster member
        Config c1 = new XmlConfigBuilder().build();
        c1.setPortAutoIncrement(false);
        c1.setPort(5709);
        // second config for super client
        Config c2 = new XmlConfigBuilder().build();
        c2.setPortAutoIncrement(false);
        c2.setPort(5710);
        // make sure to super client = true
        c2.setSuperClient(true);
        // start the normal member with c1
        HazelcastInstance hNormal = Hazelcast.newHazelcastInstance(c1);
        // start the super client with different configuration c2
        HazelcastInstance hSuper = Hazelcast.newHazelcastInstance(c2);
        hNormal.getMap("default").put("1", "first");
        assert hSuper.getMap("default").get("1").equals("first");
        hNormal.shutdown();
        hSuper.shutdown();
    }

Also remember to call Hazelcast.shutdownAll() after each test case to make sure that there is no other running member left from the previous tests.

   @After
    public void cleanup() throws Exception {
        Hazelcast.shutdownAll(); 
    }

Need more info? Check out existing tests.