Skip to content

Commit 703bdaa

Browse files
committed
#260 - ENH: Enhance @InjectTest with support for @setup methods & when @Inject, @mock provide values use them
1 parent c5c90f7 commit 703bdaa

14 files changed

+452
-65
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.BeanScopeBuilder;
4+
import io.avaje.inject.test.InjectExtension;
5+
import io.avaje.inject.test.Setup;
6+
import jakarta.inject.Inject;
7+
import org.junit.jupiter.api.Test;
8+
import org.junit.jupiter.api.extension.ExtendWith;
9+
10+
import static org.junit.jupiter.api.Assertions.assertEquals;
11+
import static org.mockito.Mockito.mock;
12+
import static org.mockito.Mockito.when;
13+
14+
@ExtendWith(InjectExtension.class)
15+
class InjectExtension_setupMethodStatic_Test {
16+
17+
static @Inject HelloService helloService;
18+
19+
static HelloData myTestDouble;
20+
21+
@Setup
22+
static void setup(BeanScopeBuilder builder) {
23+
myTestDouble = mock(HelloData.class);
24+
when(myTestDouble.helloData()).thenReturn("MockedViaSetupMethod");
25+
builder.bean(HelloData.class, myTestDouble);
26+
}
27+
28+
@Test
29+
void hello_1() {
30+
assertEquals("hello+MockedViaSetupMethod", helloService.hello());
31+
}
32+
33+
@Test
34+
void hello_2() {
35+
when(myTestDouble.helloData()).thenReturn("LocalMock_2");
36+
assertEquals("hello+LocalMock_2", helloService.hello());
37+
}
38+
39+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.BeanScopeBuilder;
4+
import io.avaje.inject.test.InjectExtension;
5+
import io.avaje.inject.test.Setup;
6+
import jakarta.inject.Inject;
7+
import org.junit.jupiter.api.Test;
8+
import org.junit.jupiter.api.extension.ExtendWith;
9+
10+
import java.util.concurrent.atomic.AtomicInteger;
11+
12+
import static org.assertj.core.api.Assertions.assertThat;
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
import static org.mockito.Mockito.mock;
15+
import static org.mockito.Mockito.when;
16+
17+
@ExtendWith(InjectExtension.class)
18+
class InjectExtension_setupMethod_Test {
19+
20+
@Inject
21+
HelloService helloService;
22+
23+
HelloData myTestDouble;
24+
25+
@Setup
26+
void setup(BeanScopeBuilder builder) {
27+
myTestDouble = mock(HelloData.class);
28+
when(myTestDouble.helloData()).thenReturn("MockedViaSetupMethod");
29+
builder.bean(HelloData.class, myTestDouble);
30+
}
31+
32+
@Test
33+
void hello_1() {
34+
assertEquals("hello+MockedViaSetupMethod", helloService.hello());
35+
}
36+
37+
@Test
38+
void hello_2() {
39+
when(myTestDouble.helloData()).thenReturn("LocalMock_2");
40+
assertEquals("hello+LocalMock_2", helloService.hello());
41+
}
42+
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.test.InjectTest;
4+
import jakarta.inject.Inject;
5+
import org.junit.jupiter.api.Test;
6+
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
9+
@InjectTest
10+
class InjectExtension_testDoubleViaInjectStatic_Test {
11+
12+
static @Inject HelloService helloService;
13+
14+
static @Inject HelloData myTestDouble = () -> "ImActuallyATestDouble";
15+
16+
@Test
17+
void hello_1() {
18+
assertEquals("hello+ImActuallyATestDouble", helloService.hello());
19+
assertEquals("ImActuallyATestDouble", myTestDouble.helloData());
20+
}
21+
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.test.InjectExtension;
4+
import jakarta.inject.Inject;
5+
import org.junit.jupiter.api.Test;
6+
import org.junit.jupiter.api.extension.ExtendWith;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
10+
@ExtendWith(InjectExtension.class)
11+
class InjectExtension_testDoubleViaInject_Test {
12+
13+
@Inject HelloService helloService;
14+
15+
@Inject HelloData myTestDouble = () -> "ImActuallyATestDouble";
16+
17+
@Test
18+
void hello_1() {
19+
assertEquals("hello+ImActuallyATestDouble", helloService.hello());
20+
assertEquals("ImActuallyATestDouble", myTestDouble.helloData());
21+
}
22+
23+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.test.InjectExtension;
4+
import jakarta.inject.Inject;
5+
import org.junit.jupiter.api.Test;
6+
import org.junit.jupiter.api.extension.ExtendWith;
7+
import org.mockito.Mock;
8+
import org.mockito.Mockito;
9+
10+
import static org.junit.jupiter.api.Assertions.assertEquals;
11+
import static org.mockito.Mockito.when;
12+
13+
@ExtendWith(InjectExtension.class)
14+
class InjectExtension_testDoubleViaMock2_Test {
15+
16+
@Inject HelloService helloService;
17+
18+
@Mock HelloData mockData = initMe();
19+
20+
private HelloData initMe() {
21+
HelloData helloData = Mockito.mock(HelloData.class);
22+
when(helloData.helloData()).thenReturn("CreatedByInitMe");
23+
return helloData;
24+
}
25+
26+
@Test
27+
void hello_1() {
28+
assertEquals("hello+CreatedByInitMe", helloService.hello());
29+
}
30+
31+
@Test
32+
void hello_2() {
33+
when(mockData.helloData()).thenReturn("LocalMock_2");
34+
assertEquals("hello+LocalMock_2", helloService.hello());
35+
}
36+
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.test.InjectExtension;
4+
import jakarta.inject.Inject;
5+
import org.junit.jupiter.api.Test;
6+
import org.junit.jupiter.api.extension.ExtendWith;
7+
import org.mockito.Mock;
8+
import org.mockito.Mockito;
9+
10+
import static org.junit.jupiter.api.Assertions.assertEquals;
11+
import static org.mockito.Mockito.when;
12+
13+
@ExtendWith(InjectExtension.class)
14+
class InjectExtension_testDoubleViaMockStatic_Test {
15+
16+
static @Inject HelloService helloService;
17+
18+
static @Mock HelloData mockData = initMe();
19+
20+
private static HelloData initMe() {
21+
HelloData helloData = Mockito.mock(HelloData.class);
22+
when(helloData.helloData()).thenReturn("CreatedByInitMe");
23+
return helloData;
24+
}
25+
26+
@Test
27+
void hello_1() {
28+
assertEquals("hello+CreatedByInitMe", helloService.hello());
29+
}
30+
31+
@Test
32+
void hello_2() {
33+
when(mockData.helloData()).thenReturn("LocalMock_2");
34+
assertEquals("hello+LocalMock_2", helloService.hello());
35+
}
36+
37+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.test.InjectExtension;
4+
import jakarta.inject.Inject;
5+
import org.junit.jupiter.api.BeforeEach;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.extension.ExtendWith;
8+
import org.mockito.Mock;
9+
10+
import static org.junit.jupiter.api.Assertions.assertEquals;
11+
12+
@ExtendWith(InjectExtension.class)
13+
class InjectExtension_testDoubleViaMock_Test {
14+
15+
@Inject HelloService helloService;
16+
17+
@Mock HelloData mockData = () -> "ImAConcreteTestDouble";
18+
19+
@Test
20+
void hello_1() {
21+
assertEquals("hello+ImAConcreteTestDouble", helloService.hello());
22+
assertEquals("ImAConcreteTestDouble", mockData.helloData());
23+
}
24+
25+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package io.avaje.inject.test;
2+
3+
import io.avaje.applog.AppLog;
4+
import io.avaje.inject.BeanScope;
5+
import org.junit.jupiter.api.extension.ExtensionContext;
6+
7+
import java.util.concurrent.locks.ReentrantLock;
8+
9+
import static java.lang.System.Logger.Level.DEBUG;
10+
import static java.lang.System.Logger.Level.TRACE;
11+
12+
/**
13+
* Holds the global BeanScope used for all tests.
14+
*/
15+
final class GlobalTestScope implements ExtensionContext.Store.CloseableResource {
16+
17+
private static final System.Logger log = AppLog.getLogger("io.avaje.inject");
18+
19+
private final ReentrantLock lock = new ReentrantLock();
20+
private boolean started;
21+
private BeanScope globalBeanScope;
22+
23+
BeanScope obtain(ExtensionContext context) {
24+
lock.lock();
25+
try {
26+
if (!started) {
27+
initialise(context);
28+
started = true;
29+
}
30+
return globalBeanScope;
31+
} finally {
32+
lock.unlock();
33+
}
34+
}
35+
36+
private void initialise(ExtensionContext context) {
37+
globalBeanScope = TestBeanScope.init(false);
38+
if (globalBeanScope != null) {
39+
log.log(TRACE, "register global test BeanScope with beans {0}", globalBeanScope);
40+
context.getRoot().getStore(ExtensionContext.Namespace.GLOBAL).put(InjectExtension.class.getCanonicalName(), this);
41+
}
42+
}
43+
44+
/**
45+
* Global shutdown of JUnit.
46+
*/
47+
@Override
48+
public void close() {
49+
lock.lock();
50+
try {
51+
if (globalBeanScope != null) {
52+
log.log(DEBUG, "Closing global test BeanScope");
53+
globalBeanScope.close();
54+
}
55+
} finally {
56+
lock.unlock();
57+
}
58+
}
59+
60+
}

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

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,65 +7,30 @@
77

88
import java.lang.System.Logger.Level;
99
import java.lang.reflect.Method;
10-
import java.util.concurrent.locks.ReentrantLock;
1110

1211
/**
1312
* Junit 5 extension for avaje inject.
1413
* <p>
1514
* Supports injection for fields annotated with <code>@Mock, @Spy, @Captor, @Inject</code>.
1615
*/
17-
public class InjectExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, ExtensionContext.Store.CloseableResource {
16+
public final class InjectExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback {
1817

1918
private static final System.Logger log = AppLog.getLogger("io.avaje.inject");
2019
private static final Namespace INJECT_NS = Namespace.create("io.avaje.inject.InjectTest");
2120
private static final String BEAN_SCOPE = "BEAN_SCOPE";
2221
private static final String META = "META";
23-
private static final ReentrantLock lock = new ReentrantLock();
24-
private static boolean started;
25-
private static BeanScope globalTestScope;
22+
private static final GlobalTestScope GLOBAL = new GlobalTestScope();
2623

27-
/**
28-
* Global shutdown of JUnit.
29-
*/
30-
@Override
31-
public void close() {
32-
lock.lock();
33-
try {
34-
if (globalTestScope != null) {
35-
log.log(Level.DEBUG, "Closing global test BeanScope");
36-
globalTestScope.close();
37-
}
38-
} finally {
39-
lock.unlock();
40-
}
41-
}
42-
43-
private void initialiseGlobalTestScope(ExtensionContext context) {
44-
globalTestScope = TestBeanScope.init(false);
45-
if (globalTestScope != null) {
46-
log.log(Level.TRACE, "register global test BeanScope with beans {0}", globalTestScope);
47-
context.getRoot().getStore(Namespace.GLOBAL).put(InjectExtension.class.getCanonicalName(), this);
48-
}
49-
}
24+
private BeanScope globalBeanScope;
5025

5126
@Override
5227
public void beforeAll(ExtensionContext context) {
53-
lock.lock();
54-
try {
55-
if (!started) {
56-
initialiseGlobalTestScope(context);
57-
started = true;
58-
}
59-
60-
final MetaInfo metaInfo = createMetaInfo(context);
61-
putMetaInfo(context, metaInfo);
28+
globalBeanScope = GLOBAL.obtain(context);
6229

63-
if (metaInfo.hasStaticInjection()) {
64-
MetaInfo.Scope testClassBeanScope = metaInfo.buildForClass(globalTestScope);
65-
putClassScope(context, testClassBeanScope);
66-
}
67-
} finally {
68-
lock.unlock();
30+
final MetaInfo metaInfo = createMetaInfo(context);
31+
putMetaInfo(context, metaInfo);
32+
if (metaInfo.hasStaticInjection()) {
33+
putClassScope(context, metaInfo.buildForClass(globalBeanScope));
6934
}
7035
}
7136

@@ -96,10 +61,10 @@ private BeanScope getClassScope(ExtensionContext context) {
9661
@Override
9762
public void beforeEach(final ExtensionContext context) {
9863
final MetaInfo metaInfo = getMetaInfo(context);
99-
if (metaInfo.hasNormalInjection()) {
64+
if (metaInfo.hasInstanceInjection()) {
10065

10166
// if (static fields) then (class scope) else (globalTestScope)
102-
final BeanScope parent = metaInfo.hasStaticInjection() ? getClassScope(context) : globalTestScope;
67+
final BeanScope parent = metaInfo.hasStaticInjection() ? getClassScope(context) : globalBeanScope;
10368

10469
AutoCloseable beanScope = metaInfo.buildForInstance(parent, context.getRequiredTestInstance());
10570

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
/**
77
* Wraps the underlying metadata (fields with annotations @Mock, @Spy, @Inject, @Captor).
88
*/
9-
class MetaInfo {
9+
final class MetaInfo {
1010

1111
private final MetaReader reader;
1212

@@ -18,7 +18,7 @@ boolean hasStaticInjection() {
1818
return reader.hasClassInjection();
1919
}
2020

21-
boolean hasNormalInjection() {
21+
boolean hasInstanceInjection() {
2222
return reader.hasInstanceInjection();
2323
}
2424

0 commit comments

Comments
 (0)