title: Spring boot how to test WebServerInitialized event
body: <p>I am trying to test functionality in an application that occurs when the app registers with a service registry.  This happens only when the app has a full web context (ie. <code>spring-boot-starter-web</code> is on the class path, and the servlet is not mocked).  This is controlled via <code>spring-cloud-commons</code> <a href="https://github.com/spring-cloud/spring-cloud-commons/blob/master/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/AbstractAutoServiceRegistration.java" rel="nofollow noreferrer">AbstractAutoServiceRegistration</a>.</p>
  
  <h1>Simple Test</h1>
  
  <p>All the test should do is the following:</p>
  
  <pre><code>1) Bring up Web App
  2) Verify auto-registration w/ service registry event fired
  3) Manually force close app
  4) Verify auto-deregistratoin occurred
  </code></pre>
  
  <h2>Approach 1: @SpringBootTest</h2>
  
  <p><code>SpringBootTest</code> makes it easy to create the full web context, which is great.  But I cannot close the app mid-test to force a deregister </p>
  
  <pre><code>@RunWith(SpringRunner.class)
  @SpringBootTest(
          classes = MyAutoConfig.class,
          webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
  )
  @EnableAutoConfiguration
  public class DiscoverySpringCloudBootMinimalRegistrationTest {
  
  @Test
  public void register_deregister {
      // Force-close app to trigger dereigster (causes exception)
      ((ConfigurableApplicationContext) context).close();
  
      verify(registry, times(1)).register(autoRegistrationServiceRecord);
      verify(registry, times(1)).deregister(autoRegistrationServiceRecord);
  }
  </code></pre>
  
  <p>The <code>context.close()</code> call results in a long error, basically saying not to manually close the context like this.</p>
  
  <pre><code>..... contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]]] is not active. This may be due to one of the following reasons: 1) the context was closed programmatically by user code; 2) the context was closed during parallel test execution either according to @DirtiesContext semantics or due to automatic eviction from the ContextCache due to a maximum cache size policy.
  </code></pre>
  
  <h2>Approach 2: WebContextRunner</h2>
  
  <p>In this approach, I avoid <code>@SpringBootTest</code> and manually configure a context runner.  This works nicely for calling <code>context.close()</code> but the web context in configures has a mock servlet, and DOES NOT trigger the <code>WebInitializedEvent</code> required for autoregistration.</p>
  
  <pre><code>public class BasicAutoConfigTests {
  
      private WebApplicationContextRunner runner;
  
      @Test
      public void register_deregister() {
  
         runner = new WebApplicationContextRunner()
                .withConfiguration(
                      AutoConfigurations.of(MyAutoConfig.class));
  
  
         runner.run((context) -&gt; {
            assertThat(context).hasNotFailed();
  
            ServiceRegistry registry = context.getBean(ServiceRegistry.class);
            ServiceRecord autoRegistration = context.getBean(MyServiceRecord.class);
            context.close();
  
            verify(registry, times(1)).register(autoRegistration);
            verify(registry, times(1)).deregister(autoRegistration);
  
        });
    }
  </code></pre>
  
  <p><strong>This almost works</strong> but results in a <code>MockServletContext</code> bean, which I presume is failing to trigger the requisite <code>WebServerInitializedEvent</code> from <code>spring-cloud-commons</code>.  How can this approach bootstrap an authentic, complete embedded tomcat server?</p>