Skip to content

Commit da13c75

Browse files
authored
Follow to #503 for Plugin scope to match the test bean scope (#507)
- Rename GlobalTestScope -> GlobalTestBeans - Lift and rename GlobalTestScope.Pair to TestBeans - The plugin scope lives in TestBeans and scoped with the associated test bean scope (created together, closed together) - Rename PluginInitialise to PluginMgr - Rename TSBuild to GlobalInitialise Note the plugin for avaje-nima creates the nima http server, so now this will be started and stopped with the associated bean scope.
1 parent e39155b commit da13c75

File tree

9 files changed

+157
-111
lines changed

9 files changed

+157
-111
lines changed

inject-test/src/main/java/io/avaje/inject/test/TSBuild.java renamed to inject-test/src/main/java/io/avaje/inject/test/GlobalInitialise.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
* Takes into when Service loading does not work such as when using module-path.
1919
* In that case loads the META-INF services resources and uses reflection.
2020
*/
21-
final class TSBuild {
21+
final class GlobalInitialise {
2222

2323
private static final ReentrantLock lock = new ReentrantLock();
24-
private static GlobalTestScope.Pair SCOPE;
24+
private static GlobalTestBeans.Beans SCOPE;
2525

2626
private final boolean shutdownHook;
2727

@@ -31,13 +31,13 @@ final class TSBuild {
3131
*/
3232
@Nullable
3333
static BeanScope createTestBaseScope(boolean shutdownHook) {
34-
return new TSBuild(shutdownHook).build();
34+
return new GlobalInitialise(shutdownHook).build();
3535
}
3636

3737
/**
3838
* Return the test BeanScope only creating once.
3939
*/
40-
static GlobalTestScope.Pair initialise(boolean shutdownHook) {
40+
static GlobalTestBeans.Beans initialise(boolean shutdownHook) {
4141
lock.lock();
4242
try {
4343
if (SCOPE == null) {
@@ -49,14 +49,15 @@ static GlobalTestScope.Pair initialise(boolean shutdownHook) {
4949
}
5050
}
5151

52-
TSBuild(boolean shutdownHook) {
52+
GlobalInitialise(boolean shutdownHook) {
5353
this.shutdownHook = shutdownHook;
5454
}
5555

56-
private static GlobalTestScope.Pair createScopes(boolean shutdownHook) {
56+
private static GlobalTestBeans.Beans createScopes(boolean shutdownHook) {
5757
BeanScope testBaseScope = createTestBaseScope(shutdownHook);
5858
BeanScope testAllScope = createTestAllScope(testBaseScope);
59-
return new GlobalTestScope.Pair(testAllScope, testBaseScope);
59+
Plugin.Scope pluginAll = PluginMgr.scope(testAllScope);
60+
return new GlobalTestBeans.Beans(pluginAll, testAllScope, testBaseScope);
6061
}
6162

6263
private static BeanScope createTestAllScope(BeanScope testBaseScope) {

inject-test/src/main/java/io/avaje/inject/test/GlobalTestScope.java renamed to inject-test/src/main/java/io/avaje/inject/test/GlobalTestBeans.java

+36-27
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,30 @@
1212
/**
1313
* Holds the global BeanScope used for all tests.
1414
*/
15-
final class GlobalTestScope implements ExtensionContext.Store.CloseableResource {
15+
final class GlobalTestBeans implements ExtensionContext.Store.CloseableResource {
1616

1717
private static final System.Logger log = AppLog.getLogger("io.avaje.inject");
1818

1919
private final ReentrantLock lock = new ReentrantLock();
2020
private boolean started;
21-
private Pair globalBeanScope;
21+
private Beans globalBeans;
2222

23-
Pair obtain(ExtensionContext context) {
23+
Beans obtain(ExtensionContext context) {
2424
lock.lock();
2525
try {
2626
if (!started) {
2727
initialise(context);
2828
started = true;
2929
}
30-
return globalBeanScope;
30+
return globalBeans;
3131
} finally {
3232
lock.unlock();
3333
}
3434
}
3535

3636
private void initialise(ExtensionContext context) {
37-
globalBeanScope = TSBuild.initialise(false);
38-
log.log(TRACE, "register global test BeanScope with beans {0}", globalBeanScope);
37+
globalBeans = GlobalInitialise.initialise(false);
38+
log.log(TRACE, "register global test BeanScope with beans {0}", globalBeans);
3939
context.getRoot().getStore(ExtensionContext.Namespace.GLOBAL).put(InjectExtension.class.getCanonicalName(), this);
4040
}
4141

@@ -46,64 +46,73 @@ private void initialise(ExtensionContext context) {
4646
public void close() {
4747
lock.lock();
4848
try {
49-
if (globalBeanScope != null) {
49+
if (globalBeans != null) {
5050
log.log(DEBUG, "Closing global test BeanScope");
51-
globalBeanScope.close();
51+
globalBeans.close();
5252
}
5353
} finally {
5454
lock.unlock();
5555
}
5656
}
5757

5858
/**
59-
* The pair of BeanScopes that can be used for InjectTests.
59+
* The BeanScopes and plugin scope that can be used for InjectTests.
6060
*/
61-
static final class Pair {
61+
static final class Beans {
62+
63+
private final Plugin.Scope plugin;
6264

6365
/**
6466
* Entire application wired (with testScope as parent replacing those beans).
6567
* This can be used when a test only injects beans and there are no mocks,
6668
* spies, or setup methods.
6769
*/
68-
private final BeanScope allScope;
70+
private final BeanScope allBeans;
6971

7072
/**
7173
* The TestScope beans, used as the parent scope when a new BeanScope
7274
* needs to be wired for a test (due to mocks, spies or setup methods).
7375
*/
74-
private final BeanScope baseScope;
76+
private final BeanScope baseBeans;
7577

76-
Pair(BeanScope allScope, BeanScope baseScope) {
77-
this.allScope = allScope;
78-
this.baseScope = baseScope;
78+
Beans(Plugin.Scope plugin, BeanScope allBeans, BeanScope baseBeans) {
79+
this.plugin = plugin;
80+
this.allBeans = allBeans;
81+
this.baseBeans = baseBeans;
7982
}
8083

8184
void close() {
82-
if (allScope != null) {
83-
allScope.close();
85+
if (plugin != null) {
86+
plugin.close();
87+
}
88+
if (allBeans != null) {
89+
allBeans.close();
8490
}
85-
if (baseScope != null) {
86-
baseScope.close();
91+
if (baseBeans != null) {
92+
baseBeans.close();
8793
}
8894
}
8995

90-
BeanScope allScope() {
91-
return allScope;
96+
Plugin.Scope allPlugin() {
97+
return plugin;
9298
}
9399

94-
BeanScope baseScope() {
95-
return baseScope;
100+
BeanScope allBeans() {
101+
return allBeans;
96102
}
97103

98-
Pair newPair(BeanScope newAllScope) {
99-
return new Pair(newAllScope, baseScope);
104+
BeanScope baseBeans() {
105+
return baseBeans;
106+
}
107+
108+
Beans withBeans(TestBeans otherBeans) {
109+
return new Beans(otherBeans.plugin(), otherBeans.beanScope(), baseBeans);
100110
}
101111

102112
@Override
103113
public String toString() {
104-
return "All[" + allScope + "] Test[" + baseScope + "]";
114+
return "All[" + allBeans + "] Test[" + baseBeans + "]";
105115
}
106-
107116
}
108117

109118
}

inject-test/src/main/java/io/avaje/inject/test/InjectExtension.java

+13-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.avaje.inject.test;
22

33
import io.avaje.applog.AppLog;
4-
import io.avaje.inject.BeanScope;
54
import org.junit.jupiter.api.extension.*;
65
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
76

@@ -19,18 +18,18 @@ public final class InjectExtension implements BeforeAllCallback, AfterAllCallbac
1918
private static final Namespace INJECT_NS = Namespace.create("io.avaje.inject.InjectTest");
2019
private static final String BEAN_SCOPE = "BEAN_SCOPE";
2120
private static final String META = "META";
22-
private static final GlobalTestScope GLOBAL = new GlobalTestScope();
21+
private static final GlobalTestBeans GLOBAL = new GlobalTestBeans();
2322

24-
private GlobalTestScope.Pair globalBeanScope;
23+
private GlobalTestBeans.Beans globalTestBeans;
2524

2625
@Override
2726
public void beforeAll(ExtensionContext context) {
28-
globalBeanScope = GLOBAL.obtain(context);
27+
globalTestBeans = GLOBAL.obtain(context);
2928

3029
final MetaInfo metaInfo = createMetaInfo(context);
3130
putMetaInfo(context, metaInfo);
3231
if (metaInfo.hasStaticInjection()) {
33-
putClassScope(context, metaInfo.buildForClass(globalBeanScope));
32+
putClassScope(context, metaInfo.buildForClass(globalTestBeans));
3433
}
3534
}
3635

@@ -44,15 +43,15 @@ private MetaInfo getMetaInfo(ExtensionContext context) {
4443
return (MetaInfo) context.getStore(INJECT_NS).get(META + testClass);
4544
}
4645

47-
private void putClassScope(ExtensionContext context, MetaInfo.Scope testClassBeanScope) {
46+
private void putClassScope(ExtensionContext context, TestBeans testClassBeanScope) {
4847
Class<?> testClass = context.getRequiredTestClass();
4948
context.getStore(INJECT_NS).put(BEAN_SCOPE + testClass, testClassBeanScope);
5049
}
5150

52-
private BeanScope getClassScope(ExtensionContext context) {
51+
private GlobalTestBeans.Beans getClassScope(ExtensionContext context, GlobalTestBeans.Beans globalTestBeans) {
5352
Class<?> testClass = context.getRequiredTestClass();
54-
MetaInfo.Scope pair = (MetaInfo.Scope) context.getStore(INJECT_NS).get(BEAN_SCOPE + testClass);
55-
return pair.beanScope();
53+
TestBeans testBeans = (TestBeans) context.getStore(INJECT_NS).get(BEAN_SCOPE + testClass);
54+
return globalTestBeans.withBeans(testBeans);
5655
}
5756

5857
/**
@@ -62,14 +61,13 @@ private BeanScope getClassScope(ExtensionContext context) {
6261
public void beforeEach(final ExtensionContext context) {
6362
final MetaInfo metaInfo = getMetaInfo(context);
6463
if (metaInfo.hasInstanceInjection()) {
65-
66-
// if (static fields) then (class scope) else (globalTestScope)
67-
final GlobalTestScope.Pair pair = metaInfo.hasStaticInjection() ? globalBeanScope.newPair(getClassScope(context)) : globalBeanScope;
68-
AutoCloseable beanScope = metaInfo.buildForInstance(pair, context.getRequiredTestInstance());
64+
// if (static fields) then (class scope) else (global scope)
65+
final GlobalTestBeans.Beans parentBeans = metaInfo.hasStaticInjection() ? getClassScope(context, globalTestBeans) : globalTestBeans;
66+
AutoCloseable metaScope = metaInfo.buildForInstance(parentBeans, context.getRequiredTestInstance());
6967

7068
// put method level test scope
7169
Method testMethod = context.getRequiredTestMethod();
72-
context.getStore(INJECT_NS).put(BEAN_SCOPE + testMethod, beanScope);
70+
context.getStore(INJECT_NS).put(BEAN_SCOPE + testMethod, metaScope);
7371
}
7472
}
7573

@@ -109,7 +107,7 @@ public void afterAll(ExtensionContext context) {
109107
* Return the MetaInfo.
110108
*/
111109
private MetaInfo createMetaInfo(ExtensionContext context) {
112-
return new MetaInfo(context.getRequiredTestClass(), PluginInitialise.plugin());
110+
return new MetaInfo(context.getRequiredTestClass(), PluginMgr.plugin());
113111
}
114112

115113
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package io.avaje.inject.test;
22

3-
import java.util.Optional;
4-
53
import io.avaje.inject.BeanScope;
64
import io.avaje.inject.BeanScopeBuilder;
75

6+
import java.util.Optional;
7+
88
/**
99
* Wraps the underlying metadata (fields with annotations @Mock, @Spy, @Inject, @Captor).
1010
*/
@@ -27,78 +27,51 @@ boolean hasInstanceInjection() {
2727
/**
2828
* Build for static fields class level scope.
2929
*/
30-
Scope buildForClass(GlobalTestScope.Pair globalTestScope) {
30+
TestBeans buildForClass(GlobalTestBeans.Beans globalTestScope) {
3131
return buildSet(globalTestScope, null);
3232
}
3333

3434
/**
3535
* Build test instance per test scope.
3636
*/
37-
Scope buildForInstance(GlobalTestScope.Pair globalTestScope, Object testInstance) {
37+
TestBeans buildForInstance(GlobalTestBeans.Beans globalTestScope, Object testInstance) {
3838
return buildSet(globalTestScope, testInstance);
3939
}
4040

41-
private Scope buildSet(GlobalTestScope.Pair parent, Object testInstance) {
41+
private TestBeans buildSet(GlobalTestBeans.Beans parent, Object testInstance) {
42+
var testBeans = buildTestBeans(parent, testInstance);
43+
// set inject, spy, mock fields from beanScope
44+
return reader.setFromScope(testBeans, testInstance);
45+
}
46+
47+
private TestBeans buildTestBeans(GlobalTestBeans.Beans parent, Object testInstance) {
4248
// wiring profiles
4349
String[] profiles = Optional.ofNullable(testInstance)
4450
.map(Object::getClass)
4551
.map(c -> c.getAnnotation(InjectTest.class))
4652
.map(InjectTest::profiles)
4753
.orElse(new String[0]);
4854

49-
boolean newScope = false;
50-
final BeanScope beanScope;
5155
if (profiles.length > 0 || reader.hasMocksOrSpies(testInstance)) {
52-
// need to build a BeanScope for this using testScope() as the parent
56+
// need to build a BeanScope for this using baseBeans() as the parent
5357
final BeanScopeBuilder builder = BeanScope.builder();
5458
if (parent != null) {
55-
builder.parent(parent.baseScope(), false);
59+
builder.parent(parent.baseBeans(), false);
5660
if (profiles.length > 0) {
5761
builder.profiles(profiles);
5862
}
5963
}
6064
// register mocks and spies local to this test
6165
reader.build(builder, testInstance);
62-
// wire with local mocks, spies, and globalTestScope
63-
beanScope = builder.build();
64-
newScope = true;
66+
// wire with local mocks, spies, and TestScope beans
67+
var newBeanScope = builder.build();
68+
var newPlugin = PluginMgr.scope(newBeanScope);
69+
return new TestBeans(newBeanScope, newPlugin);
70+
6571
} else {
66-
// just use the all scope
67-
beanScope = parent.allScope();
72+
// just use the existing beans and plugin from parent
73+
return new TestBeans(parent);
6874
}
69-
70-
// set inject, spy, mock fields from beanScope
71-
return reader.setFromScope(beanScope, testInstance, newScope);
7275
}
7376

74-
/**
75-
* Wraps both BeanScope and Plugin.Scope for either EACH or ALL
76-
* (aka instance or class level).
77-
*/
78-
static class Scope implements AutoCloseable {
79-
80-
private final BeanScope beanScope;
81-
private final Plugin.Scope pluginScope;
82-
private final boolean newScope;
83-
84-
Scope(BeanScope beanScope, Plugin.Scope pluginScope, boolean newScope) {
85-
this.beanScope = beanScope;
86-
this.pluginScope = pluginScope;
87-
this.newScope = newScope;
88-
}
89-
90-
BeanScope beanScope() {
91-
return beanScope;
92-
}
93-
94-
@Override
95-
public void close() {
96-
if (newScope) {
97-
beanScope.close();
98-
}
99-
if (pluginScope != null) {
100-
pluginScope.close();
101-
}
102-
}
103-
}
10477
}

0 commit comments

Comments
 (0)