@Test
public void testAddAndRemoveListener() throws InterruptedException {

    configuration.publishConfig(KEY, "A");
    AtomicBoolean processedEvent = new AtomicBoolean();
    configuration.addListener(KEY, event -> {
        processedEvent.set(true);
        assertEquals(KEY, event.getKey());
        logger.info(String.format("[%s] " + event + "\n", Thread.currentThread().getName()));
    });
    configuration.publishConfig(KEY, "B");
    while (!processedEvent.get()) {
        Thread.sleep(1 * 1000L);
    }
    processedEvent.set(false);
    configuration.publishConfig(KEY, "C");
    while (!processedEvent.get()) {
        Thread.sleep(1 * 1000L);
    }
    processedEvent.set(false);
    configuration.publishConfig(KEY, "D");
    while (!processedEvent.get()) {
        Thread.sleep(1 * 1000L);
    }
    configuration.addListener("test", "test", event -> {
        processedEvent.set(true);
        assertEquals("test", event.getKey());
        logger.info(String.format("[%s] " + event + "\n", Thread.currentThread().getName()));
    });
    processedEvent.set(false);
    configuration.publishConfig("test", "test", "TEST");
    while (!processedEvent.get()) {
        Thread.sleep(1 * 1000L);
    }
    configuration.publishConfig("test", "test", "TEST");
    configuration.publishConfig("test", "test", "TEST");
    configuration.publishConfig("test", "test", "TEST");
    processedEvent.set(false);
    configuration.getRootDirectory();
    File keyFile = new File(KEY, DEFAULT_GROUP);
    FileUtils.deleteQuietly(keyFile);
    while (!processedEvent.get()) {
        Thread.sleep(1 * 1000L);
    }
}