Expand test coverage for routing and annotation scanning: validate distinct handlers for same path with different methods, ensure correct MethodNotAllowed responses, and handle overwriting/parameterized paths.
Auto Publish on Version Change / check-and-publish (push) Successful in 14s
Run Tests on Push and Pull Request / run-tests (push) Successful in 18s

This commit is contained in:
CodingPhoenixx
2026-05-28 13:48:05 +02:00
parent 78d90855c5
commit efd302f625
2 changed files with 121 additions and 0 deletions
@@ -110,4 +110,45 @@ class AnnotationScannerTest {
assertThrows(IllegalArgumentException.class, assertThrows(IllegalArgumentException.class,
() -> AnnotationScanner.register(router, new WrongReturnType())); () -> AnnotationScanner.register(router, new WrongReturnType()));
} }
@Controller("/users")
static class CrudController {
java.util.concurrent.atomic.AtomicInteger getCalls = new java.util.concurrent.atomic.AtomicInteger();
java.util.concurrent.atomic.AtomicInteger putCalls = new java.util.concurrent.atomic.AtomicInteger();
java.util.concurrent.atomic.AtomicInteger deleteCalls = new java.util.concurrent.atomic.AtomicInteger();
@GET("/")
public void list(Request req, Response res) { getCalls.incrementAndGet(); }
@PUT("/")
public void replace(Request req, Response res) { putCalls.incrementAndGet(); }
@DELETE("/")
public void wipe(Request req, Response res) { deleteCalls.incrementAndGet(); }
}
@Test
void multipleMethodsOnSamePathRouteToDistinctHandlers() throws Exception {
Router router = new Router();
CrudController ctrl = new CrudController();
AnnotationScanner.register(router, ctrl);
var get = assertInstanceOf(Router.Resolution.Match.class, router.resolve(HttpMethod.GET, "/users/"));
var put = assertInstanceOf(Router.Resolution.Match.class, router.resolve(HttpMethod.PUT, "/users/"));
var del = assertInstanceOf(Router.Resolution.Match.class, router.resolve(HttpMethod.DELETE, "/users/"));
get.handler().handle(null, new Response());
put.handler().handle(null, new Response());
del.handler().handle(null, new Response());
assertEquals(1, ctrl.getCalls.get());
assertEquals(1, ctrl.putCalls.get());
assertEquals(1, ctrl.deleteCalls.get());
var post = router.resolve(HttpMethod.POST, "/users/");
var mna = assertInstanceOf(Router.Resolution.MethodNotAllowed.class, post);
assertTrue(mna.allowedMethods().contains(HttpMethod.GET));
assertTrue(mna.allowedMethods().contains(HttpMethod.PUT));
assertTrue(mna.allowedMethods().contains(HttpMethod.DELETE));
}
} }
@@ -80,4 +80,84 @@ class RouterTest {
match.handler().handle(null, null); match.handler().handle(null, null);
assertEquals(1, called.get()); assertEquals(1, called.get());
} }
@Test
void samePathWithDifferentMethodsResolvesToDistinctHandlers() throws Exception {
AtomicInteger getCalls = new AtomicInteger();
AtomicInteger putCalls = new AtomicInteger();
AtomicInteger deleteCalls = new AtomicInteger();
Router r = new Router()
.get("/user", (req, res) -> getCalls.incrementAndGet())
.put("/user", (req, res) -> putCalls.incrementAndGet())
.delete("/user", (req, res) -> deleteCalls.incrementAndGet());
var get = assertInstanceOf(Router.Resolution.Match.class, r.resolve(HttpMethod.GET, "/user"));
var put = assertInstanceOf(Router.Resolution.Match.class, r.resolve(HttpMethod.PUT, "/user"));
var del = assertInstanceOf(Router.Resolution.Match.class, r.resolve(HttpMethod.DELETE, "/user"));
get.handler().handle(null, null);
put.handler().handle(null, null);
del.handler().handle(null, null);
assertEquals(1, getCalls.get());
assertEquals(1, putCalls.get());
assertEquals(1, deleteCalls.get());
assertNotSame(get.handler(), put.handler());
assertNotSame(put.handler(), del.handler());
}
@Test
void samePathUnregisteredMethodReturnsMethodNotAllowedWithAllAllowed() {
Router r = new Router()
.get("/user", noop)
.put("/user", noop)
.delete("/user", noop);
var res = r.resolve(HttpMethod.POST, "/user");
var mna = assertInstanceOf(Router.Resolution.MethodNotAllowed.class, res);
assertTrue(mna.allowedMethods().contains(HttpMethod.GET));
assertTrue(mna.allowedMethods().contains(HttpMethod.PUT));
assertTrue(mna.allowedMethods().contains(HttpMethod.DELETE));
assertFalse(mna.allowedMethods().contains(HttpMethod.POST));
assertEquals(3, mna.allowedMethods().size());
}
@Test
void registeringSameMethodAndPathTwiceOverwritesHandler() throws Exception {
AtomicInteger first = new AtomicInteger();
AtomicInteger second = new AtomicInteger();
Router r = new Router()
.get("/user", (req, res) -> first.incrementAndGet())
.get("/user", (req, res) -> second.incrementAndGet());
var match = (Router.Resolution.Match) r.resolve(HttpMethod.GET, "/user");
match.handler().handle(null, null);
assertEquals(0, first.get());
assertEquals(1, second.get());
}
@Test
void samePathWithParamAndMultipleMethodsKeepsParamsAndHandlers() throws Exception {
AtomicInteger getCalls = new AtomicInteger();
AtomicInteger putCalls = new AtomicInteger();
Router r = new Router()
.get("/user/{id}", (req, res) -> getCalls.incrementAndGet())
.put("/user/{id}", (req, res) -> putCalls.incrementAndGet());
var get = assertInstanceOf(Router.Resolution.Match.class, r.resolve(HttpMethod.GET, "/user/42"));
var put = assertInstanceOf(Router.Resolution.Match.class, r.resolve(HttpMethod.PUT, "/user/42"));
assertEquals("42", get.pathParams().get("id"));
assertEquals("42", put.pathParams().get("id"));
get.handler().handle(null, null);
put.handler().handle(null, null);
assertEquals(1, getCalls.get());
assertEquals(1, putCalls.get());
assertNotSame(get.handler(), put.handler());
}
} }