Class MockRestServerExtension

java.lang.Object
com.shri.restinpeace.mock.MockRestServerExtension
All Implemented Interfaces:
org.junit.jupiter.api.extension.AfterAllCallback, org.junit.jupiter.api.extension.BeforeAllCallback, org.junit.jupiter.api.extension.BeforeEachCallback, org.junit.jupiter.api.extension.Extension, org.junit.jupiter.api.extension.ParameterResolver, org.junit.jupiter.api.extension.TestInstantiationAwareExtension

public final class MockRestServerExtension extends Object implements org.junit.jupiter.api.extension.BeforeAllCallback, org.junit.jupiter.api.extension.AfterAllCallback, org.junit.jupiter.api.extension.BeforeEachCallback, org.junit.jupiter.api.extension.ParameterResolver
A JUnit 5 extension that starts one MockRestServer for a whole test class and resets it before each test - register it with @ExtendWith and receive the server as a test (or @BeforeEach) method parameter, instead of wiring up @BeforeAll/@AfterAll/@BeforeEach boilerplate by hand.
 @ExtendWith(MockRestServerExtension.class)
 class OrderServiceTest {

     private OrderApi api;

     @BeforeEach
     void setUp(MockRestServer server) {
         api = RIP.getClient(OrderApi.class, server.baseUrl());
     }

     @Test
     void placesAnOrder(MockRestServer server) {
         server.on(HTTPMethod.GET, "/orders/{id}", MockResponse.ok("{}"));
         ...
     }
 }
 

Because the server (and so its MockRestServer.baseUrl()) is the same object for every test method in the class, a @RestClient built from it - like api above - can be built once in @BeforeEach instead of needing the fresh base URL a new server per test would otherwise force.

Registration: the server starts in a BeforeAllCallback, which JUnit only invokes for an extension it can discover before any test instance exists - that means @ExtendWith(MockRestServerExtension.class) on the class (as above), or a static field annotated @RegisterExtension. Registering it on a non-static @RegisterExtension field silently skips server startup and shutdown, since JUnit can't read an instance field before an instance exists - prefer @ExtendWith unless a test specifically needs to keep a reference to the extension itself via getServer().

Isolation: every test method in the class shares the same server - MockRestServer.reset() between tests clears routes, queued responses, and recorded requests, but the server itself, and everything built against its base URL, is not safe for concurrent use. Don't combine this extension with parallel test execution within the same class.

Requires junit-jupiter-api on the consumer's own test classpath - a provided-scope dependency of this library, not a transitive runtime one, so using this class is opt-in and costs a consumer who doesn't nothing.

Unhit-route reporting: reportUnhitRoutes() opts into printing every route (MockRestServer.getUnhitRoutes()) still unhit when the test class finishes - a route left registered after the code path that used to exercise it was removed otherwise causes no failure at all. This only works with the static @RegisterExtension field style, since @ExtendWith(MockRestServerExtension.class) has JUnit construct the extension itself via the no-arg constructor, with no way to call reportUnhitRoutes() first:

 class OrderServiceTest {

     @RegisterExtension
     static MockRestServerExtension extension = new MockRestServerExtension().reportUnhitRoutes();

     @Test
     void placesAnOrder(MockRestServer server) {
         server.on(HTTPMethod.GET, "/orders/{id}", MockResponse.ok("{}"));
         // ... a test that never actually calls /orders/{id} prints a warning at afterAll
     }
 }
 
  • Nested Class Summary

    Nested classes/interfaces inherited from interface org.junit.jupiter.api.extension.TestInstantiationAwareExtension

    org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope
  • Constructor Summary

    Constructors
    Constructor
    Description
    Creates the extension - register it via @ExtendWith, it needs no arguments.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    afterAll(org.junit.jupiter.api.extension.ExtensionContext context)
     
    void
    beforeAll(org.junit.jupiter.api.extension.ExtensionContext context)
     
    void
    beforeEach(org.junit.jupiter.api.extension.ExtensionContext context)
     
    Returns the server for the current test class - only meaningful once beforeAll has run.
    Opts into printing every unhit route to System.err at afterAll - see this class's own javadoc for why this only takes effect with the static @RegisterExtension field style.
    resolveParameter(org.junit.jupiter.api.extension.ParameterContext parameterContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext)
     
    boolean
    supportsParameter(org.junit.jupiter.api.extension.ParameterContext parameterContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext)
     

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface org.junit.jupiter.api.extension.TestInstantiationAwareExtension

    getTestInstantiationExtensionContextScope
  • Constructor Details

    • MockRestServerExtension

      public MockRestServerExtension()
      Creates the extension - register it via @ExtendWith, it needs no arguments.
  • Method Details

    • reportUnhitRoutes

      public MockRestServerExtension reportUnhitRoutes()
      Opts into printing every unhit route to System.err at afterAll - see this class's own javadoc for why this only takes effect with the static @RegisterExtension field style. Purely a diagnostic: it never fails the test class, whether or not any route is left unhit.
      Returns:
      this extension, for chaining onto the @RegisterExtension field assignment
    • getServer

      public MockRestServer getServer()
      Returns the server for the current test class - only meaningful once beforeAll has run. Prefer receiving MockRestServer as a parameter (see the class javadoc) over calling this directly; it exists for the static @RegisterExtension field registration style, where no test instance is available to resolve a parameter against (e.g. a static @BeforeAll method).
      Returns:
      this class's server
    • beforeAll

      public void beforeAll(org.junit.jupiter.api.extension.ExtensionContext context)
      Specified by:
      beforeAll in interface org.junit.jupiter.api.extension.BeforeAllCallback
    • beforeEach

      public void beforeEach(org.junit.jupiter.api.extension.ExtensionContext context)
      Specified by:
      beforeEach in interface org.junit.jupiter.api.extension.BeforeEachCallback
    • afterAll

      public void afterAll(org.junit.jupiter.api.extension.ExtensionContext context)
      Specified by:
      afterAll in interface org.junit.jupiter.api.extension.AfterAllCallback
    • supportsParameter

      public boolean supportsParameter(org.junit.jupiter.api.extension.ParameterContext parameterContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext) throws org.junit.jupiter.api.extension.ParameterResolutionException
      Specified by:
      supportsParameter in interface org.junit.jupiter.api.extension.ParameterResolver
      Throws:
      org.junit.jupiter.api.extension.ParameterResolutionException
    • resolveParameter

      public Object resolveParameter(org.junit.jupiter.api.extension.ParameterContext parameterContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext) throws org.junit.jupiter.api.extension.ParameterResolutionException
      Specified by:
      resolveParameter in interface org.junit.jupiter.api.extension.ParameterResolver
      Throws:
      org.junit.jupiter.api.extension.ParameterResolutionException