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.
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>
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.
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.
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.
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.