5

The main WebServerExtension example from the JUnit5 manual is incomplete and it doesn't fully show how to properly store the configuration (e.g. enableSecurity, server url).

https://github.com/junit-team/junit5/blob/master/documentation/src/main/java/example/registration/WebServerExtension.java

The example ignores or hard codes the values. The manual (section 5.11. Keeping State in Extensions) implies that the "Store" should be used but the ExtensionContext is not yet available yet when the object is constructed -- its not clear how to handle migrating this data to the Store as the ExtensionContext is not yet available in the constructor.

Also its not clear to me that using the Store API for the WebServerExtension programmatic example is even desirable and perhaps it could work just using the internal state (e.g. this.serverUrl, this.enableSecurity, etc.).

Maybe the Store is more applicable to Extensions which don't use this "programmatic" style where multiple instances of the custom extension may exist (appropriately)? In other words its not clear to me from the guide if this a supported paradigm or not?

Other JUnit 5 extension examples online (e.g. org.junit.jupiter.engine.extension.TempDirectory) show how to leverage annotations to handle passing configuration info to the Store but it would be nice if there were a complete programmatic builder type example like WebServerExtension too.

Examples like TempDirectory clearly have access to the ExtensionContext from the beforeXXX() methods whereas the WebServerExtension example does not.

Using the following approach below seems to work fine but I wanted confirmation that this is a supported paradigm (i.e. using fields instead of Stores when using this programmatic approach).

    public class WebServerExtension implements BeforeAllCallback {
      private final boolean securityEnabled;
      private final String serverUrl;
      public WebServerExtension(Builder builder) {
        this.securityEnabled = builder.enableSecurity;
        this.serverUrl = build.serverUrl;
      }   

      @Override
      public void beforeAll(ExtensionContext context) {
        // is it ok to use this.securityEnabled, this.serverUrl instead of Store API???
      }

      public String getServerUrl() {
        return this.serverUrl;
      }

      public boolean isSecurityEnabled() {
        return this.securityEnabled;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private boolean enableSecurity;
        private String serverUrl;
        public Builder enableSecurity(boolean b) {
          this.enableSecurity = b;
          return this;
        }
        public Builder serverUrl(String url) {
          this.serverUrl = url;
          return this;
        }
        public WebServerExtension build() {
          return new WebServerExtension(this);
        }
      }
    }

Thanks!

Kirk Rasmussen
  • 231
  • 4
  • 9
  • 1
    If you're using `@RegisterExtension` to programmatically register an extension, you are responsible for creating the instance of the extension. So it should typically be fine to store state within the extension instance in such cases. You just need to make sure the same extension is never registered via `@ExtendWith`. – Sam Brannen Apr 09 '19 at 12:27
  • 1
    If you feel that the User Guide can be improved in this regard, feel free to open an issue in the JUnit 5 GitHub issue tracker. – Sam Brannen Apr 09 '19 at 12:27

0 Answers0