Skip to content

diffplug/durian-globals

Repository files navigation

DurianGlobals: Easy-to-test singletons

Maven central Apache 2.0

Changelog Javadoc Live chat JitCI

Usage

Provides an easy way to initialize a singleton exactly once:

public class Singleton {
  public static Singleton instance() {
    return Globals.getOrSetTo(Singleton.class, Singleton::new);
  }

  protected Singleton() {}
  ...
}

In a testing environment, you can wipe the globals to get a clean state or to replace the standard implementation with a testing one.

public class SingletonTest {
  static class SingletonDev extends Singleton {
    ...
  }

  @Test
  public void someTest() {
    try (AutoCloseable wipeGlobals = GlobalsDev.wipe()) {
      SingletonDev dev = new SingletonDev();
      GlobalsDev.install(Singleton.class, dev);
      ...
    }
  }
}

The "trick" is that GlobalsDev is shipped in a different artifact than the rest, so you can be sure that your Globals can only be changed in tests, and never in production code:

dependencies {
  implementation     'com.diffplug.durian-globals:durian-globals:1.0.0'
  testImplementation 'com.diffplug.durian-globals:durian-globals.dev:1.0.0'
}

Built-ins

There are some globals that people frequently want control over during testing.

Time

You can use public static long Time.now() as a replacement for System.currentTimeMillis(). And in a test, you can replace it with TimeDev.

@Test
public void someTimeDependentTest() {
  try (AutoCloseable wipeGlobals = GlobalsDev.wipe()) {
    TimeDev time = TimeDev.install();
    time.setUTC(LocalDate.parse("2019-03-30"));
    ... // exercise code that uses `Time.now()`
  }
}

Requirements

DurianGlobals requires nothing but Java 8+.

In the wild

Acknowledgements