Skip to content

Testing

Testing should be relatively straightforward if you are using injection for the Registry. Consider a sample class:

public class Foo {

  private final Counter counter;

  @Inject
  public Foo(Registry registry) {
    counter = registry.counter("foo");
  }

  public void doSomething() {
    counter.increment();
  }
}

Tests will typically want to use an isolated instance of the DefaultRegistry.

Simple Test

A basic standalone test class would look something like:

public class FooTest {

  private Registry registry;
  private Foo foo;

  @Before
  public void init() {
    registry = new DefaultRegistry();
    foo = new Foo(registry);
  }

  @Test
  public void doSomething() {
    foo.doSomething();
    Assert.assertEquals(1, registry.counter("foo").count());
  }
}

Spring Test

If using Spring, then you can create a binding for the DefaultRegistry, for example:

public class FooTest {

  private Registry registry;
  private Foo foo;

  @Configuration
  public static class TestConfiguration {
    @Bean
    public Registry registry() {
      return new DefaultRegistry();
    }

    @Bean
    public Foo foo(Registry registry) {
      return new Foo(registry);
    }
  }

  private AnnotationConfigApplicationContext createContext() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(TestConfiguration.class);
    context.refresh();
    return context;
  }

  @Test
  public void doSomething() {
    try (AnnotationConfigApplicationContext context = createContext()) {
      Foo foo = context.getBean(Foo.class);
      foo.doSomething();

      Registry registry = context.getBean(Registry.class);
      Assert.assertEquals(1, registry.counter("foo").count());
    }
  }
}

Exceptions

By default, for most user errors Spectator will log a warning rather than throw an exception. The rationale is that users do not often think about instrumentation and logging code causing an exception and interrupting the control flow of a program. However, for test cases it is recommended to be more aggressive and learn about problems as early as possible. This can be done by setting a system property:

spectator.api.propagateWarnings=true

Consider an example:

private static final Id RARE_EXCEPTION_ID = null;

public void doSomethingImportant() {
  try {
    ... do work ...
  } catch (RareException e) {
    // There is a bug in the program, an Id is not allowed to be null. In production we do
    // not want it to throw and interrupt the control flow. Instrumentation should gracefully
    // degrade.
    registry.counter(RARE_EXCEPTION_ID).increment();

    // These statements are important to provide context for operating the system
    // and to ensure the app continues to function properly.
    LOGGER.error("important context for user", e);
    properlyHandleException(e);
  }
}