Testing since 1.1.0

Togglz has to be properly initialized before it can be used. In most application setups this is done automatically. Unit tests are problematic in this regard, because they run in a minimal environment and test code that may use Togglz to control behavior. Togglz therefore provides extended support for managing feature state when running unit tests.

To add the Togglz testing support module, add the following dependency to your project. Please double check that you add it only for the test scope.

<!-- Togglz testing support -->
<dependency>
  <groupId>org.togglz</groupId>
  <artifactId>togglz-testing</artifactId>
  <version>3.1.2</version>
  <scope>test</scope>
</dependency> 

Including this dependency will automatically configure Togglz in a way that is considered the best default behavior for unit tests. In this default setup every call to isActive() will return true, which means that all features are automatically active.

If you need more control over your feature state, you should have a look at the extended JUnit support that is convered in the next section.

JUnit 4 support

Togglz provides some extra goodies for JUnit users. If you are using JUnit, you should always include the JUnit support module in your test depdencies.

<!-- Togglz testing support -->
<dependency>
  <groupId>org.togglz</groupId>
  <artifactId>togglz-junit</artifactId>
  <version>3.1.2</version>
  <scope>test</scope>
</dependency>

TogglzRule

The first important feature of the JUnit integration module is the TogglzRule. This rule allows to modify the feature state at runtime. This is especially useful if you want to test a special combination of feature states.

public class SomeJunitTest {

  @Rule
  public TogglzRule togglzRule = TogglzRule.allEnabled(MyFeatures.class);

  @Test
  public void testToggleFeature() {

    // all features are active by default  
    assertTrue(MyFeatures.FEATURE_ONE.isActive());

    // you can easily modify the feature state using the TogglzRule
    togglzRule.disable(MyFeatures.FEATURE_ONE);
    assertFalse(MyFeatures.FEATURE_ONE.isActive());

  }

}

To use the rule, declare a public field for TogglzRule as shown above and annotate it with JUnit's @Rule annotation. TogglzRule provides static methods for creating a preconfigured feature state. In this example the rule initally enables all features of the MyFeatures enum.

The test first verifies that the feature is enabled. Then the method uses the TogglzRule to alter the feature state by calling disable() for the feature. The rule provides methods for changing the state of individual features and bulk operations for enabling or disabling all feature toggles at once.

Feature variations

The JUnit integration module also allows to run tests with different combination of feature states. This works very similar to JUnit's @Parameterized annotation.

Before explaining the details, see the following code:

@RunWith(FeatureVariations.class)
public class FeatureVariationsTest {

    @Variations
    public static VariationSet<MyFeatures> getPermutations() {
      return VariationSetBuilder.create(MyFeatures.class)
              .enable(MyFeatures.F1)
              .vary(MyFeatures.F2)
              .vary(MyFeatures.F3);
    }

    // will be executed 4 times
    @Test
    public void test() {
      assertTrue(MyFeatures.F1.isActive());
      assertTrue(MyFeatures.F2.isActive() || !MyFeatures.F2.isActive());
      assertTrue(MyFeatures.F3.isActive() || !MyFeatures.F3.isActive());
    }

}

To run your tests in different feature combinations, your test class has to be annotated with @RunWith(FeatureVariations.class). This will tell JUnit to use a special JUnit runner called FeatureVariations for executing the test.

In the next step you have to create a public static method returning a VariationSet and annotate it with @Variations. A VariationSet is used describe the feature combinations that you want the test to get executed with. Typically you should use VariationSetBuilder to build the set, because it provides a fluent API for defining it. In the example shown above, the feature set will vary the features F2 and F3 and keep F1 enabled. This means your test methods will be executed four times, once for each of these combinations:

  • F1=on, F2=off, F3=off
  • F1=on, F2=on, F3=off
  • F1=on, F2=off, F3=on
  • F1=on, F2=on, F3=on

This way of running unit tests is very effective if you want to verify, that the state of a feature has no effect on the output of your code.

JUnit 5 support

Togglz also provides support for JUnit 5 aka JUnit Jupiter. Just add the following dependency in addition to the togglz-testing dependency

<!-- Togglz testing support -->
<dependency>
  <groupId>org.togglz</groupId>
  <artifactId>togglz-junit</artifactId>
  <version>3.1.2</version>
  <scope>test</scope>
</dependency>

When using JUnit 5 there is no need for a JUnit Rule anymore.

class AnnotationBasedTogglzExtensionTest {

  @Test
  @AllEnabled(MyFeatures.class)
  void allEnabled() {
      assertTrue(MyFeatures.ONE.isActive());
      assertTrue(MyFeatures.TWO.isActive());
      assertTrue(MyFeatures.THREE.isActive());
  }

  @Test
  @AllDisabled(MyFeatures.class)
  void allDisabled() {
      assertFalse(MyFeatures.ONE.isActive());
      assertFalse(MyFeatures.TWO.isActive());
      assertFalse(MyFeatures.THREE.isActive());
  }

}

You can enable and disable all Features by using the @AllEnabled and @AllDisabled annotations. The first test enables and the second one disables all three Features of the MyFeatures enum class. In case you want to enable or disable specific Features you can add org.togglz.testing.TestFeatureManager as method parameter.

class AnnotationBasedTogglzExtensionTest {

  @Test
  @AllEnabled(MyFeatures.class)
  void testFeatureManagerParameter(TestFeatureManager featureManager) {
      assertTrue(MyFeatures.ONE.isActive());

      featureManager.disable(MyFeatures.ONE);
      assertFalse(MyFeatures.ONE.isActive());

      featureManager.enable(MyFeatures.ONE);
      assertTrue(MyFeatures.ONE.isActive());
  }
}

Like in the examples before you have to annotate the test method with @AllEnabled or @AllDisabled. Depending on how many specific Features you want to disable or enable. In addition to that you can enable and disable specific Features by using the TestFeatureManager enable() and disable() methods like in the example above.

Feature variations

The JUnit Jupiter integration module also allows to run tests with different combination of feature states. Variating Features in JUnit Jupiter is little a bit different to the JUnit 4 one. First you have to use the TestTemplate and @VaryFeatures annotations instead of the @Test and @AllEnabled or @AllDisabled annotations. After that you have to add a VariationSetProvider to your test class and as an argument to the @VaryFeatures annotation.

class FeatureVariationTogglzExtensionTest {

  @TestTemplate
  @VaryFeatures(TestingVariationSetProvider.class)
  void variations() {
      assertTrue(MyFeatures.ONE.isActive());
      assertFalse(MyFeatures.TWO.isActive());

      // active or not active, that is the question
      assertTrue(MyFeatures.THREE.isActive() || !MyFeatures.THREE.isActive());
  }

  private static class TestingVariationSetProvider implements VariationSetProvider {

      @Override
      public VariationSet<? extends Feature> buildVariationSet() {
          return create(MyFeatures.class).enable(MyFeatures.ONE).disable(MyFeatures.TWO).vary(MyFeatures.THREE);
      }
  }
}

The VariationSetProvider allows you to enable, disable and vary specific Features. In this example Feature ONE is enabled, Feature TWO disabled and the state of feature THREE varies every execution. This way of running unit tests is very effective if you want to verify, that the state of a feature has no effect on the output of your code.