Package dev.relism.flash.testing
Class FlashTest
java.lang.Object
dev.relism.flash.testing.FlashTest
- All Implemented Interfaces:
org.junit.jupiter.api.extension.AfterAllCallback,org.junit.jupiter.api.extension.AfterEachCallback,org.junit.jupiter.api.extension.BeforeAllCallback,org.junit.jupiter.api.extension.BeforeEachCallback,org.junit.jupiter.api.extension.Extension
public final class FlashTest
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.AfterEachCallback
Boots a real
FlashApp on an OS-assigned port for the duration of a test class or a
single test, and gives you a client pointed at it.
class UserRoutesTest {
@RegisterExtension
static FlashTest app = FlashTest.of(new BlogApp())
.mock(UserService.class, new InMemoryUserService());
@Test
void listsUsers() {
app.get("/api/users")
.expectStatus(200)
.expectBodyContains("alice");
}
}
More than one server
Because this is an ordinary object in a field rather than an annotation, a test class can hold as many as it needs, and one can be wired from another with plain Java. Startup is lazy — readingbaseUri() boots that server on the spot — so declaration order does the
wiring, with no reliance on JUnit's extension ordering:
@RegisterExtension static FlashTest auth = FlashTest.of(new FakeOidcApp());
@RegisterExtension static FlashTest api = FlashTest.of(new BlogApp(auth.baseUri()));
Scope
Astatic field boots once for the class; a non-static field boots a fresh app for
every test. That is stock JUnit field semantics — the isolation switch is the keyword.
Replacing services
mock(java.lang.Class<T>, T) installs its replacements as the last extension, after everything the
application and its extensions declare, so a fake always wins. Any object will do — a
hand-written fake or a Mockito mock you created; this module depends on no mocking library.- See Also:
-
Method Summary
Modifier and TypeMethodDescriptionvoidafterAll(org.junit.jupiter.api.extension.ExtensionContext context) voidafterEach(org.junit.jupiter.api.extension.ExtensionContext context) dev.relism.flash.extension.FlashAppapp()The running app — escape hatch for assertions the harness does not cover.baseUri()Base URI of the running server, e.g.voidbeforeAll(org.junit.jupiter.api.extension.ExtensionContext context) voidbeforeEach(org.junit.jupiter.api.extension.ExtensionContext context) client()The client the harness issues requests with.SendsDELETE pathwith no headers or body.SendsGET pathwith no headers or body.<T> FlashTestReplaces the service bound totypewithinstancefor this server.static FlashTestof(dev.relism.flash.extension.FlashApplication application) Creates a harness forapplication.intport()OS-assigned port of the running server.Customises theFlashConfigurationthis server runs with — timeouts, HTTP/2 switches, buffer sizes.request()Starts a request with headers or a body; the HTTP verb sends it.Opens a WebSocket topathon this server.
-
Method Details
-
of
Creates a harness forapplication. Nothing is bound or started until first use.FlashApplicationis a functional interface, so a lambda works as well as a named class:FlashTest.of(app -> app.get("/ping", (req, res) -> "pong")). -
profile
public FlashTest profile(Consumer<dev.relism.flash.extension.FlashConfiguration.FlashConfigurationBuilder> profile) Customises theFlashConfigurationthis server runs with — timeouts, HTTP/2 switches, buffer sizes.The harness stamps host, port and the shutdown drain window after this runs, so a profile cannot break it. Setting
listener(...)ortls(...)is rejected: the harness owns the single plaintext loopback listener it hands you a client for. -
mock
Replaces the service bound totypewithinstancefor this server.Wins over anything the application or its extensions declare, including services provided by an installed
FlashExtension.ponytail: overrides are applied to the app's root context. A service declared inside a
mount(...)scope's child context shadows the root and is therefore not reachable — add child-context targeting if that ever comes up. -
baseUri
Base URI of the running server, e.g.http://127.0.0.1:41307. -
port
public int port()OS-assigned port of the running server. -
app
public dev.relism.flash.extension.FlashApp app()The running app — escape hatch for assertions the harness does not cover. -
client
The client the harness issues requests with. -
request
Starts a request with headers or a body; the HTTP verb sends it. -
get
SendsGET pathwith no headers or body. -
delete
SendsDELETE pathwith no headers or body. -
ws
Opens a WebSocket topathon this server. Close it when done — a try-with-resources block is the usual shape. -
beforeAll
public void beforeAll(org.junit.jupiter.api.extension.ExtensionContext context) - Specified by:
beforeAllin interfaceorg.junit.jupiter.api.extension.BeforeAllCallback
-
afterAll
public void afterAll(org.junit.jupiter.api.extension.ExtensionContext context) - Specified by:
afterAllin interfaceorg.junit.jupiter.api.extension.AfterAllCallback
-
beforeEach
public void beforeEach(org.junit.jupiter.api.extension.ExtensionContext context) - Specified by:
beforeEachin interfaceorg.junit.jupiter.api.extension.BeforeEachCallback
-
afterEach
public void afterEach(org.junit.jupiter.api.extension.ExtensionContext context) - Specified by:
afterEachin interfaceorg.junit.jupiter.api.extension.AfterEachCallback
-