Repository navigation
Install the empty Guice module loader before the suite in openam-scripting and openam-audit-context tests #1187
Description
Context
#1186 fixed a class-order dependence in the openam-core-rest tests. InjectorHolder builds its injector once per JVM, from the module loader InjectorConfiguration holds at that moment. A test class that reaches it before another class installs its loader therefore decides which injector every later class gets. The review of #1186 pointed at the same pattern in other modules, where tests install their loader in @BeforeClass or @BeforeMethod rather than before the suite.
Current state
Measured at 5eb929e, with the class order fixed by a TestNG suite XML (-Dsurefire.suiteXmlFiles). No order of a module's own test classes fails today, so the hazard is latent.
openam-scripting. The default loader cannot build an injector on this test classpath:No implementation for NotificationBroker was bound, throughCoreGuiceModule->SessionGuiceModule.GroovyValidatorTest,JavaScriptValidatorTestandGroovyAstTransformEscapeTestinstall an empty loader in their@BeforeMethod setupGuiceModules()override. That happens beforeGuiceTestCase.setupGuiceModules()first reaches the holder, and none of the other 23 classes touches it.- A new class could reach
InjectorHolderwithout a hook, for example throughSupportedScriptingLanguage.getScriptValidator(),ScriptEngineConfigurator.updateConfigorScriptingSetupListener. If it runs first, all three classes fail insetupGuiceModuleswithNoClassDefFoundError: Could not initialize class org.forgerock.guice.core.InjectorHolder. - Reproduced with a scratch class of that kind.
- A new class could reach
openam-audit/openam-audit-context.AuditContextFilterTestis the only test class, and it installs its loader in@BeforeClass. Here the default loader builds an empty injector.- A new unhooked class that runs first leaves
AuditContextFilterTestwith that injector, and both of its tests fail withNo implementation for TransactionIdConfiguration was bound. - Reproduced with a scratch class.
- A new unhooked class that runs first leaves
openam-datastore. Nothing to do. No test reachesInjectorHolder, so nothing reads the loaderIdRepoTestBaseinstalls in@BeforeClass.
Proposed change
Test code only. In openam-scripting and openam-audit-context, install the empty loader from @BeforeSuite(alwaysRun = true), as IdentityResourceNotificationTest does in openam-core-rest after #1186.
In openam-scripting, one such hook in GroovyValidatorTest was enough to make the scratch-class order above pass. Once the holder has been built, GuiceTestCase registers a fresh injector for every test method.
The limits that apply in openam-core-rest apply here too:
- The hook covers the other classes only while surefire runs the module as one TestNG suite in one JVM, that is with the inherited
forkCount=1andreuseForks=true. - TestNG creates an instance of every test class before it runs any
@BeforeSuitemethod. A constructor or initializer that reachesInjectorHolderstill comes first.
Activity
[OpenIdentityPlatform#1187] Install the scripting tests' empty Guice …
[OpenIdentityPlatform#1187] Reset the audit context test's trust flag…
maximthomas commentedon Oct 20, 2026
RestRouterITinopenam-rest, raised in the #1188 review, is out of scope here. It installs an empty loader from a@BeforeMethod, but it needs none: the default loader builds the root injector on that module's test classpath. Measured on master 553b73f: a scratch class that touchesInjectorHolderwith no loader installed, run first, builds it, andRestRouterITthen passes 8 of 8. With its loader install deleted,RestRouterITalone also passes 8 of 8.GuiceTestCaseregisters the test's own injector before each method andRestRouterITreads only from that one, so class order cannot change its result.[OpenIdentityPlatform#1187] Install the Guice module loader before th…