Skip to content

Commit fb86925

Browse files
aksOpsclaude
andauthored
refactor(test): slice UnifiedConfigBeansTest to ApplicationContextRunner (#50) (#55)
Replace full @SpringBootTest bootstrap with ApplicationContextRunner that loads only UnifiedConfigBeans + ProjectConfigLoader. All 4 tests pass in under a second vs. multi-second full-context startup, same correctness guarantee for the config-wiring surface. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 8ed60f5 commit fb86925

1 file changed

Lines changed: 30 additions & 24 deletions

File tree

src/test/java/io/github/randomcodespace/iq/config/UnifiedConfigBeansTest.java

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
import io.github.randomcodespace.iq.config.unified.ConfigResolver;
66
import org.junit.jupiter.api.Test;
77
import org.junit.jupiter.api.io.TempDir;
8-
import org.springframework.beans.factory.annotation.Autowired;
9-
import org.springframework.boot.test.context.SpringBootTest;
10-
import org.springframework.test.context.ActiveProfiles;
8+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
119

1210
import java.nio.file.Files;
1311
import java.nio.file.Path;
@@ -23,37 +21,45 @@
2321
* bean that is the single source of truth, and the legacy {@link CodeIqConfig} bean
2422
* is produced by adapting the unified bean.
2523
*
24+
* <p>Uses {@link ApplicationContextRunner} to spin up a minimal context containing
25+
* only {@link UnifiedConfigBeans} + {@link ProjectConfigLoader}, rather than booting
26+
* the full application via {@code @SpringBootTest}. Sub-second per test vs.
27+
* multi-second full-context startup, same correctness guarantee for this surface.
28+
*
2629
* <p>The "defaults path" assertions here run with no {@code codeiq.yml} in cwd,
2730
* so values must match {@link io.github.randomcodespace.iq.config.unified.ConfigDefaults}
2831
* — which in turn matches the values that were historically in {@code application.yml}.
2932
*/
30-
@SpringBootTest
31-
@ActiveProfiles("test")
3233
class UnifiedConfigBeansTest {
3334

34-
@Autowired
35-
CodeIqUnifiedConfig unified;
36-
37-
@Autowired
38-
CodeIqConfig legacy;
35+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
36+
.withBean(ProjectConfigLoader.class)
37+
.withUserConfiguration(UnifiedConfigBeans.class);
3938

4039
@Test
4140
void contextExposesUnifiedAndLegacyBeansBothBackedBySameSource() {
42-
assertNotNull(unified, "unified config bean must be present");
43-
assertNotNull(legacy, "legacy config bean must be present");
44-
// Same cacheDir — proves the legacy bean is adapted from unified.
45-
assertEquals(unified.indexing().cacheDir(), legacy.getCacheDir());
41+
contextRunner.run(ctx -> {
42+
CodeIqUnifiedConfig unified = ctx.getBean(CodeIqUnifiedConfig.class);
43+
CodeIqConfig legacy = ctx.getBean(CodeIqConfig.class);
44+
assertNotNull(unified, "unified config bean must be present");
45+
assertNotNull(legacy, "legacy config bean must be present");
46+
// Same cacheDir — proves the legacy bean is adapted from unified.
47+
assertEquals(unified.indexing().cacheDir(), legacy.getCacheDir());
48+
});
4649
}
4750

4851
@Test
4952
void defaultsMatchHistoricalApplicationYmlValues() {
50-
// These values came from application.yml pre-Task-11; they must still
51-
// be what CodeIqConfig exposes now that wiring goes through ConfigDefaults.
52-
assertEquals(".code-iq/cache", legacy.getCacheDir());
53-
assertEquals(".code-iq/graph/graph.db", legacy.getGraph().getPath());
54-
assertEquals(10, legacy.getMaxDepth());
55-
assertEquals(10, legacy.getMaxRadius());
56-
assertEquals(500, legacy.getBatchSize());
53+
contextRunner.run(ctx -> {
54+
CodeIqConfig legacy = ctx.getBean(CodeIqConfig.class);
55+
// These values came from application.yml pre-Task-11; they must still
56+
// be what CodeIqConfig exposes now that wiring goes through ConfigDefaults.
57+
assertEquals(".code-iq/cache", legacy.getCacheDir());
58+
assertEquals(".code-iq/graph/graph.db", legacy.getGraph().getPath());
59+
assertEquals(10, legacy.getMaxDepth());
60+
assertEquals(10, legacy.getMaxRadius());
61+
assertEquals(500, legacy.getBatchSize());
62+
});
5763
}
5864

5965
/**
@@ -62,9 +68,9 @@ void defaultsMatchHistoricalApplicationYmlValues() {
6268
* names the offending file path, so a user can find and fix the broken yml.
6369
*
6470
* <p>Tested at the {@link ConfigResolver} level (not via Spring context restart)
65-
* because relocating CWD inside a single {@code @SpringBootTest} run is fragile.
66-
* The Spring wiring in {@link UnifiedConfigBeans#codeIqUnifiedConfig()} calls
67-
* exactly this resolver, so the guarantee propagates: Spring wraps the
71+
* because relocating CWD inside a single context run is fragile. The Spring
72+
* wiring in {@link UnifiedConfigBeans#codeIqUnifiedConfig} calls exactly this
73+
* resolver, so the guarantee propagates: Spring wraps the
6874
* {@code ConfigLoadException} in a {@code BeanCreationException} at startup.
6975
*/
7076
@Test

0 commit comments

Comments
 (0)