| Artifact | io.github.microsphere-projects:microsphere-java-test (0.3.20-SNAPSHOT, release branch) |
| Packages | io.microsphere.test.annotation (1 type) · io.microsphere.test.model (11 types) · io.microsphere.test.service (4 types) — 16 main-source types, no other code |
| Contents | 1 annotation interface + 1 interface + 1 enum + 13 classes (one of them, StringArrayList, extends ArrayList<String>) = 16 types; 14 JUnit 5 test classes |
| JDK level | No maven.compiler.* / <release> property exists anywhere in the reactor — the bytecode level is inherited from the external parent microsphere-build:0.3.16 (pom.xml:6-10); CI-tested on JDK 8 / 11 / 17 / 21 / 25 (Temurin) |
| In-repo compile dependency | io.github.microsphere-projects:microsphere-java-annotations, declared optional (microsphere-java-test/pom.xml:24-29) |
| Other declared dependencies | junit-jupiter, junit-jupiter-engine, mockito-core, logback-classic, javax.ws.rs-api, jaxws-api, spring-context, spring-web — every one optional, none with <scope>test</scope> (microsphere-java-test/pom.xml:31-84) |
| Shipped resources | src/main/resources/junit-platform.properties, src/main/resources/logback-test.xml — both land inside the jar and on consumers' test classpaths |
Note
Citation shorthand used on this page. Paths are relative to microsphere-java-test/src/main/java/io/microsphere/
for module sources (test/model/Model.java:29), and to microsphere-java-test/src/test/java/io/microsphere/ for its
own tests (test/model/ModelTest.java:23). Cross-module paths are written in full
(microsphere-java-core/pom.xml:66-71).
This module is the shared fixture layer of Microsphere Java. It publishes sixteen deliberately boring types — a POJO inheritance chain, a set of "one field per type kind" models, an enum, a reflection-heavy annotation, and a small service interface hierarchy — whose only job is to give the other modules something stable and non-trivial to reflect over, compile against, and annotation-process. Nothing here is a production API, and nothing here has logic: every method is a getter, a setter, or a one-line stub.
Reach for this artifact when you are writing tests for Microsphere itself (or for a project that reuses its
fixtures) and you need a type shape that exercises a code path — Model extends Parent extends Ancestor to test
hierarchical field walking, CollectionTypeModel to test generic-component resolution, TestAnnotation to test
annotation-attribute resolution across all eight member types. Adding the jar should cost nothing at runtime, because
none of its types is ever loaded by production code.
| I want to test… | Fixture | Why that fixture |
|---|---|---|
| Walking fields up a class hierarchy | test/model/Ancestor.java:27, test/model/Parent.java:25, test/model/Model.java:29 |
Three-level chain Model → Parent → Ancestor, one field per level (z / b,s,i,l / f,d,tu,str,bi,bd) |
| Resolving primitive-typed fields | test/model/PrimitiveTypeModel.java:25 |
All eight primitives, getters only — no setters (test/model/PrimitiveTypeModel.java:43-73) |
Resolving boxed/"simple" types incl. Void |
test/model/SimpleTypeModel.java:29 |
Void, Boolean, Character, …, BigDecimal, BigInteger, java.util.Date |
Component types of Collection generics |
test/model/CollectionTypeModel.java:31 |
Collection<String>, List<Color>, Queue<PrimitiveTypeModel>, Deque<Model>, Set<Model[]> |
Key/value types of Map generics |
test/model/MapTypeModel.java:31 |
Map, SortedMap, NavigableMap, HashMap, TreeMap — declared types vary on purpose |
| Array component types | test/model/ArrayTypeModel.java:25 |
int[], String[], PrimitiveTypeModel[], Model[], Color[] |
| A parameterized supertype | test/model/StringArrayList.java:29 |
extends ArrayList<String> — the type argument is fixed by inheritance, not by a field |
| Enum constants with state | test/model/Color.java:25 |
RED(1), YELLOW(2), BLUE(3) + getValue() + overridden toString() |
| Reading annotation member values reflectively | test/annotation/TestAnnotation.java:43 |
One attribute per supported member type (test/annotation/TestAnnotation.java:45-71) |
| Configuration-metadata extraction | test/model/ConfigurationPropertyModel.java:29 |
Five fields each carrying @ConfigurationProperty(name = …) |
| Interface + impl + proxy resolution | test/service/TestService.java:36, test/service/TestServiceImpl.java:77 |
JAX-RS, Spring and JAX-WS annotations stacked on one type |
Four reasons the fixtures live in their own module rather than being duplicated into each consumer's src/test:
- The same type shape must be assertable from two different vantage points.
microsphere-java-corereflects on these classes at runtime;microsphere-lang-modelandmicrosphere-annotation-processorinspect the same classes asTypeElement/DeclaredTypeobjects insidejavac. A private copy in each test tree would make those two views incomparable. - All dependencies are
optional, so the consumer's versions win. The module asks for JUnit, Mockito, Logback, JAX-RS, JAX-WS and Spring asoptional(microsphere-java-test/pom.xml:31-84), which means none of them is exported transitively; the consumer declares its own version (microsphere-lang-model/pom.xml:30-91). - It keeps a heavy annotation surface out of the production artifacts.
TestServiceImplalone stacks@Service,@ServiceMode,@ComponentScans,@TestAnnotationand@Cacheable(test/service/TestServiceImpl.java:41-76); that belongs in a test jar, not inmicrosphere-java-core. - Reactor order already puts it before its consumers. It is the 6th module built (
pom.xml:63, modules listed atpom.xml:58-66), ahead ofmicrosphere-annotation-test(:64),microsphere-lang-model(:65) andmicrosphere-annotation-processor(:66).
graph TD
ANNO["microsphere-java-annotations"] -. optional .-> JTEST["microsphere-java-test"]
JTEST -. test scope .-> CORE["microsphere-java-core"]
JTEST -. test scope .-> JDKTOOLS["microsphere-jdk-tools"]
JTEST --> ATEST["microsphere-annotation-test"]
CORE --> JDKTOOLS
JDKTOOLS --> ATEST
ATEST -. test scope .-> LANGMODEL["microsphere-lang-model"]
LANGMODEL --> AP["microsphere-annotation-processor"]
Important
The edge from microsphere-java-test to microsphere-annotation-test is not test-scoped.
microsphere-annotation-test declares the dependency with no <scope> element at all
(microsphere-annotation-test/pom.xml:24-28), i.e. default compile scope. That is deliberate: it is what makes
the fixtures visible to downstream test code in microsphere-lang-model
(microsphere-lang-model/src/test/java/io/microsphere/lang/model/util/TypeUtilsTest.java:19-28) and
microsphere-annotation-processor without each of them re-declaring microsphere-java-test.
<dependency>
<groupId>io.github.microsphere-projects</groupId>
<artifactId>microsphere-java-test</artifactId>
<version>0.3.20</version> <!-- newest published tag; 0.3.20-SNAPSHOT is this same line's working version -->
<scope>test</scope> <!-- the scope every consumer in the reactor uses, except microsphere-annotation-test -->
</dependency>| Field | Value | Evidence |
|---|---|---|
| Group ID | io.github.microsphere-projects |
pom.xml:12 |
| Artifact ID | microsphere-java-test |
microsphere-java-test/pom.xml:14 |
| Version | ${revision} = 0.3.20-SNAPSHOT on release |
pom.xml:54, microsphere-java-test/pom.xml:15 |
| Position in the reactor | 6th module built | pom.xml:63 (modules :58-66) |
| Packaging | jar |
microsphere-java-test/pom.xml:16 |
| Name / description | Microsphere :: Java :: Test / Microsphere Java Test |
microsphere-java-test/pom.xml:18-19 |
| Parent | microsphere-java-parent:${revision} |
microsphere-java-test/pom.xml:5-10 |
| Build parent (grandparent) | microsphere-build:0.3.16 |
pom.xml:6-10 |
| In-repo dependency | microsphere-java-annotations, optional, no <version> element — inherits ${revision} |
microsphere-java-test/pom.xml:24-29 |
| Where third-party versions come from | imported BOM microsphere-all-bom:0.3.13 + spring-framework-bom |
microsphere-java-parent/pom.xml:22, :31-37, :39-46 |
| Consumable BOM | microsphere-java-dependencies manages this artifact |
microsphere-java-dependencies/pom.xml:42-46 |
| Test-scope consumers | microsphere-java-core, microsphere-jdk-tools |
microsphere-java-core/pom.xml:66-71, microsphere-jdk-tools/pom.xml:45-48 |
| Compile-scope consumer | microsphere-annotation-test |
microsphere-annotation-test/pom.xml:24-28 |
Warning
Pin the version yourself. Because every dependency in this module is optional, nothing about the module's own POM
tells Maven which JUnit, Mockito or Spring a consumer should have; and because the artifact's own version is
${revision} (microsphere-java-test/pom.xml:15), the managed entry in microsphere-java-dependencies
(microsphere-java-dependencies/pom.xml:42-46) only carries ${revision} too. Outside the reactor, write
<version>0.3.20</version> explicitly.
| Fact | Value | Evidence |
|---|---|---|
| Release line | release branch |
— |
| Working version | 0.3.20-SNAPSHOT |
pom.xml:54 |
| Newest published tag | 0.3.20 |
release notes / Maven Central |
Declared @since (javadoc) |
1.0.0 on all sixteen main-source types |
test/annotation/TestAnnotation.java:38, test/model/Model.java:27, test/service/TestService.java:33, test/service/TestServiceImpl.java:39 |
| JDK compatibility | 8, 11, 17, 21, 25 (Temurin) | .github/workflows/maven-build.yml:25, :33 |
| Surefire flag used in CI | -Dsurefire.useSystemClassLoader=false |
.github/workflows/maven-build.yml:43 |
| Spring Framework range | 5.3.39 on JDK [1.8,17) via profile java8-16; 7.0.9 otherwise |
microsphere-java-parent/pom.xml:23, :54-62 (activation :57) |
| Bytecode level | Not set in this repository — inherited from microsphere-build:0.3.16 |
no maven.compiler.* / <release> property anywhere in the reactor |
| JAX-WS / JAX-RS availability | javax.* (Java EE) namespaces, not jakarta.* |
test/service/TestService.java:21-26, test/service/TestServiceImpl.java:30 |
The JDK story for a fixture module is mostly about which annotations can be read, because that is all the module does:
| Concern | JDK 8 | JDK 9 / 11 / 17 / 21 / 25 | Evidence |
|---|---|---|---|
Reflecting over Model / Color / TestService |
works | works | no JDK-internal API is referenced anywhere in the 16 files |
javax.ws.rs.* on TestService |
needs javax.ws.rs-api |
same | microsphere-java-test/pom.xml:59-63, test/service/TestService.java:21-26 |
javax.xml.ws.ServiceMode on TestServiceImpl |
needs jaxws-api |
same | microsphere-java-test/pom.xml:66-70, test/service/TestServiceImpl.java:30, :42 |
Spring annotations on TestServiceImpl |
needs spring-context |
same, but the resolved Spring version switches at 17 | microsphere-java-test/pom.xml:73-83, microsphere-java-parent/pom.xml:54-62 |
| JAX-RS / JAX-WS / Spring absent from the consumer classpath | the fixture classes still load; getAnnotations() returns an empty array for the missing type |
same | silent-missing-annotation behaviour — see §9 |
Tip
Treat the optional-dependency list, not the JDK version, as the compatibility surface of this module. If your
test asserts that TestServiceImpl carries @Service, your build must also resolve spring-context; the fixtures
will not fail to compile without it, they will simply report fewer annotations.
| Item | Value | Evidence |
|---|---|---|
| Documented line | release, ${revision} = 0.3.20-SNAPSHOT |
root pom.xml:54 |
| Newest published release | 0.3.20, tagged 2026-10-16 |
the 0.3.20 tag resolves to chore: merge main into release [skip ci], committed 2026-10-16T03:43:20Z |
| Previous release | 0.3.19, tagged 2026-08-30 |
the 0.3.19 tag, committed 2026-08-30T12:51:37Z |
| Changelog source | release-notes.md at the repository root |
The project publishes no CHANGELOG.md; the v0.3.16–v0.3.20 blocks of release-notes.md read Release notes generation failed and carry raw commit lists, so every entry below is quoted as a commit subject and checked against the release sources. |
0.3.20 adds no new API surface for this area — the 0.3.19...0.3.20 range is a hardening release. What it does change, and how far that reaches the sources this page documents:
- Nullability contracts. 0 of 16 main sources in the scope of this page declare
@Nonnull/@Nullable. - No other change in this range touches the area this page covers.
Note
Reading the commit list: No subject in the range names microsphere-java-test, and none of its 16 sources carries @Nonnull / @Nullable — the nullability pass stopped at the library modules and did not reach the test fixtures. Nothing in 0.3.19...0.3.20 is attributable to this module.
TestAnnotation is the module's only annotation, and it exists to be a coverage target for annotation-attribute
resolution — it declares one attribute for each kind of value a Java annotation can hold.
@Retention(RUNTIME)
@Target(TYPE)
@Documented
public @interface TestAnnotation {
boolean z() default false;
char c() default 'a';
byte b() default 1;
short s() default 2;
int i() default 3;
long l() default 4L;
float f() default 5.0f;
double d() default 6.0d;
String string() default "string";
Class<?> type() default String.class;
Class<?>[] types() default {String.class, Integer.class};
TimeUnit timeUnit() default DAYS;
Since since();
ConfigurationProperty[] properties() default {};
}| Attribute | Kind | Default | Line |
|---|---|---|---|
z |
boolean |
false |
test/annotation/TestAnnotation.java:45 |
c |
char |
'a' |
:47 |
b |
byte |
1 |
:49 |
s |
short |
2 |
:51 |
i |
int |
3 |
:53 |
l |
long |
4L |
:55 |
f |
float |
5.0f |
:57 |
d |
double |
6.0d |
:59 |
string |
String |
"string" |
:61 |
type |
Class<?> |
String.class |
:63 |
types |
Class<?>[] |
{String.class, Integer.class} |
:65 |
timeUnit |
enum-valued | DAYS |
:67 |
since |
annotation-valued | none — you must supply it | :69 |
properties |
array-of-annotation | {} (empty) |
:71 |
Two properties of this declaration matter to consumers:
- Retention is
RUNTIME, target isTYPEonly (test/annotation/TestAnnotation.java:40-42). You can read it withgetAnnotation(TestAnnotation.class), andmicrosphere-lang-modelconfirms the target set throughassertElementTypes(TestAnnotation.class, TYPE)(microsphere-lang-model/src/test/java/io/microsphere/lang/model/util/AnnotationUtilsTest.java:714). since()has no default (test/annotation/TestAnnotation.java:69), so every use site must writesince = @Since("1.0.0")— see the only in-module use site attest/service/TestServiceImpl.java:70. This forces nested-annotation resolution to be exercised rather than skipped.
The one real use site spells out every attribute at once:
@TestAnnotation(
z = true,
c = 'b',
b = 1,
s = 1,
i = 1,
l = 1,
f = 1,
d = 1,
string = "testService",
type = GenericTestService.class,
types = {TestService.class, AutoCloseable.class, Serializable.class},
timeUnit = HOURS,
since = @Since("1.0.0"),
properties = {
@ConfigurationProperty(name = "key", type = String.class, defaultValue = "default-value", required = true, description = "description"),
@ConfigurationProperty(name = "key2", type = Integer.class, defaultValue = "default-value2", required = true, description = "description2"),
@ConfigurationProperty(name = "key3", type = Class.class, defaultValue = "default-value3", required = true, description = "description3")
}
)That block (test/service/TestServiceImpl.java:57-76) is what the lang-model tests harvest as annotation values —
getElementValues(super.testTypeElement, TestAnnotation.class) returns a
Map<ExecutableElement, AnnotationValue> used at microsphere-lang-model/src/test/java/io/microsphere/lang/model/util/AnnotationUtilsTest.java:523,
:532, :543, :552, :567 and :596.
Eleven types, split into three roles.
The inheritance chain — Ancestor (test/model/Ancestor.java:27, implements Serializable, one boolean z),
Parent extends Ancestor (test/model/Parent.java:25, byte b, short s, int i, long l), Model extends Parent
(test/model/Model.java:29, float f, double d, TimeUnit tu, String str, BigInteger bi, BigDecimal bd).
A Model instance therefore carries 11 inherited-and-own fields spread across three classes:
Model model = new Model();
assertEquals(0.0f, model.getF(), "float field f should be 0.0f by default");
assertNull(model.getTu(), "TimeUnit field tu should be null by default");
assertTrue(model instanceof Parent, "Model should extend Parent class");Taken from this module's own test at test/model/ModelTest.java:29, :33, :84.
The one-field-per-type-kind models — PrimitiveTypeModel (test/model/PrimitiveTypeModel.java:25) and
SimpleTypeModel (test/model/SimpleTypeModel.java:29) are read-only vs read-write on purpose: PrimitiveTypeModel
exposes only getters (test/model/PrimitiveTypeModel.java:43-73), so a bean-copy or injection utility that assumes
setters will behave observably differently against the two. SimpleTypeModel is the wrapper-boxing catalogue, and it
is the only model type carrying a field with no accessor at all — private int invalid (test/model/SimpleTypeModel.java:57).
The composite-type catalogue — ArrayTypeModel (test/model/ArrayTypeModel.java:25), CollectionTypeModel
(test/model/CollectionTypeModel.java:31), MapTypeModel (test/model/MapTypeModel.java:31) and StringArrayList
(test/model/StringArrayList.java:29). Each field's declared raw type is different, and the comments in the source
record which element kind is under test:
private Collection<String> strings; // The composite element is simple type
private List<Color> colors; // The composite element is Enum type
private Queue<PrimitiveTypeModel> primitiveTypeModels; // The composite element is POJO type
private Deque<Model> models; // The composite element is hierarchical POJO type
private Set<Model[]> modelArrays; // The composite element is hierarchical POJO type(test/model/CollectionTypeModel.java:33-41.) MapTypeModel mirrors the same five element kinds but declares two of
its fields with concrete types, HashMap<String, Model> models and TreeMap<PrimitiveTypeModel, Model[]> modelArrays
(test/model/MapTypeModel.java:39, :41) — useful when a consumer must prove it reads the declared type rather than
the interface it widens to.
The value-carriers — Color (test/model/Color.java:25) is an enum with a constructor parameter and an
overridden toString() (test/model/Color.java:37-42), which makes it a non-trivial enum for both reflective and
javax.lang.model readers. ConfigurationPropertyModel (test/model/ConfigurationPropertyModel.java:29) is the
metadata fixture:
@ConfigurationProperty(name = "microsphere.annotation.processor.model.name")
private String name;
@ConfigurationProperty(name = "microsphere.annotation.processor.model.type")
private Class<?> type;(test/model/ConfigurationPropertyModel.java:31-35; the remaining three fields at :37, :40, :43 cover
defaultValue, required and description.) Its property names are prefixed
microsphere.annotation.processor.…, which is the giveaway that it was written for the processor's metadata output.
Four types forming one interface and a three-level implementation ladder.
classDiagram
TestService <.. DefaultTestService
TestService <.. GenericTestService
TestService <.. TestServiceImpl
DefaultTestService <|-- GenericTestService
GenericTestService <|-- TestServiceImpl
EventListener <.. GenericTestService
AutoCloseable <.. TestServiceImpl
Serializable <.. TestServiceImpl
class TestService {
<<interface>>
+echo(String) String
+model(Model) Model
+testPrimitive(boolean,int) String
+testEnum(TimeUnit) Model
+testArray(String[],int[],Model[]) String
}
class DefaultTestService {
+echo(String) String
+model(Model) Model
+testPrimitive(boolean,int) String
+testEnum(TimeUnit) Model
+testArray(String[],int[],Model[]) String
}
class GenericTestService {
+echo(String) String
}
class TestServiceImpl {
+echo(String) String
+close() void
}
TestService(test/service/TestService.java:36) carries JAX-RS metadata:@Path("/echo")on the type (:35),@GET/@POST/@PUTon the five methods (:38,:41,:45,:49,:53) and@PathParam("message") @DefaultValue("mercyblitz")on theechoparameter (:39). It also declares a method-level type parameter that nothing uses:<T> String echo(@PathParam("message") … String message)(:39) — a fixture for "does my type resolver notice a spurious type variable?"DefaultTestService(test/service/DefaultTestService.java:29) is the complete implementation:echoreturns"[ECHO] " + message(:34-36),modelreturns its argument (:39-41), andtestPrimitive/testEnum/testArrayreturnnull(:44-46,:49-51,:54-56).GenericTestService(test/service/GenericTestService.java:27) extendsDefaultTestService, adds theTestServiceandjava.util.EventListenerinterfaces, and overrides onlyechowith an identical body (:28-31). TheEventListenermarker is the interesting part — it is what lets a test assert "marker interface detected" without any other change.TestServiceImpl(test/service/TestServiceImpl.java:77) extendsGenericTestServiceand implementsTestService,AutoCloseableandSerializable, then decorates itself with every framework annotation surface the module has:@Service("testService")(:41),@ServiceMode(:42),@ComponentScanswith two@ComponentScanentries including an ASPECTJ filter andscopedProxy = INTERFACES(:43-56),@TestAnnotation(:57-76),@Autowiredon a protected field (:79-80) and@Cacheable(cacheNames = {"cache-1", "cache-2"})onecho(:93).
Two constructors exist so that both injection styles can be exercised: TestServiceImpl() delegates with null
(:84-86) and TestServiceImpl(@Autowired Environment environment) (:88-90). This module's own test uses both:
testService = new TestServiceImpl(mockEnvironment);
testService.context = mockContext; // Inject mocked ApplicationContext(test/service/TestServiceImplTest.java:31-32; new TestServiceImpl() and the assertNull(service.environment, …)
check at :72-73.)
TestService is also the fixture that proves hierarchy flattening works. From
microsphere-lang-model/src/test/java/io/microsphere/lang/model/util/TypeUtilsTest.java:121-151 the expected walks are
literal:
private static final Type[] ALL_TYPES = ofArray(SELF_TYPE, SUPER_CLASS, DefaultTestService.class, Object.class, TestService.class, EventListener.class, AutoCloseable.class, Serializable.class);(TypeUtilsTest.java:131, with SELF_TYPE = TestServiceImpl.class at :121 and SUPER_CLASS = GenericTestService.class
at :126.)
src/main/resources contains exactly two files, and neither is under a META-INF/services directory:
junit.jupiter.extensions.autodetection.enabled = true(src/main/resources/junit-platform.properties:1.) The second is a full Logback configuration —
src/main/resources/logback-test.xml — which declares a FILE appender writing test.log
(src/main/resources/logback-test.xml:5-12), an ASYNC wrapper around it (:14-16), a STDOUT console appender
(:18-22), root level="INFO" (:24-26) and a dedicated io.microsphere logger at TRACE with
additivity="false" (:28-30).
Warning
These two files are packaged into the jar and therefore reach every consumer's test classpath, where
junit-platform.properties and logback-test.xml are both auto-discovered by name. Concretely: depending on this
module turns on JUnit 5 extension auto-detection for your whole test run, and pins io.microsphere to TRACE into
an async test.log file. See §9 for how to override both.
This module ships no META-INF/services entries of its own; the service-loader files in the reactor belong to
microsphere-java-core and microsphere-annotation-processor.
A. Declare the dependency the way the reactor does (microsphere-java-core/pom.xml:65-71):
<!-- Microsphere Java Test -->
<dependency>
<groupId>io.github.microsphere-projects</groupId>
<artifactId>microsphere-java-test</artifactId>
<version>${revision}</version>
<scope>test</scope>
</dependency>B. Reflect over the composite models. The lang-model tests feed the fixtures straight into a compiled-class set
(microsphere-lang-model/src/test/java/io/microsphere/lang/model/util/TypeUtilsTest.java:190-193):
compiledClasses.add(ArrayTypeModel.class);
compiledClasses.add(CollectionTypeModel.class);
compiledClasses.add(Color.class);
compiledClasses.add(MapTypeModel.class);and then assert type-kind predicates against them — assertTrue(isEnumType(getDeclaredType(Color.class))) at
TypeUtilsTest.java:272, assertFalse(isArrayType(getTypeElement(Color.class))) at :260,
assertTrue(isClassType(getTypeElement(ArrayTypeModel.class))) at :285.
C. Reference the whole service ladder from a test (TypeUtilsTest.java:25-28, used at :121-151):
import io.microsphere.test.service.DefaultTestService;
import io.microsphere.test.service.GenericTestService;
import io.microsphere.test.service.TestService;
import io.microsphere.test.service.TestServiceImpl;D. Collections with mixed element kinds — the pattern this module's own tests use to build fixtures
(test/model/CollectionTypeModelTest.java:56-62):
List<Color> testList = asList(RED, BLUE, YELLOW);
model.setColors(testList);
assertSame(testList, model.getColors(), "Should return the same list reference that was set");
// Verify the contents match
assertEquals(testList, model.getColors(), "List contents should match the set value");test/model/CollectionTypeModelTest.java:124-134 goes further and documents the aliasing contract: mutating the
original ArrayList after setColors is still visible through getColors(), because the setters store the reference
(test/model/CollectionTypeModel.java:55-57).
E. Consume @TestAnnotation through the annotation-processing harness. The processor tests extend the
microsphere-annotation-test base class, which is itself the compile-scope consumer of this module
(microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/ResourceProcessorTest.java:20,
FilerProcessorTest.java:20, ConfigurationPropertyAnnotationProcessorTest.java:20,
ConfigurationPropertyJSONElementVisitorTest.java:26).
- Confusing this module's
io.microsphere.test.*with core'sio.microsphere.testpackage.microsphere-java-core/src/test/java/io/microsphere/test/holds an unrelated, much larger fixture set —A,B,C,D,E,Data,MultipleValueData,StringIntegerHashMap,StringBF2, … (e.g. imports atmicrosphere-java-core/src/test/java/io/microsphere/reflect/TypeUtilsTest.java:22-29andmicrosphere-java-core/src/test/java/io/microsphere/json/JSONUtilsTest.java:22-27). Those classes are not in this artifact. Ifimport io.microsphere.test.Model;fails, you have guessed the wrong package — this module's model types live underio.microsphere.test.model. - Expecting transitive JUnit/Mockito/Spring. Every dependency is
optional(microsphere-java-test/pom.xml:31-84), which by Maven semantics suppresses transitivity. Depending onmicrosphere-java-testalone does not putjunit-jupiteron your test classpath; you must declare it, exactly asmicrosphere-lang-modeldoes (microsphere-lang-model/pom.xml:31-41). - Getting Logback and extension auto-detection for free. See the warning in §7 — both
src/main/resources/logback-test.xmlandsrc/main/resources/junit-platform.propertiesship inside the jar and are discovered by name. If your project already has alogback-test.xml, classpath order decides which one wins; if you do not want autodetection, setjunit.jupiter.extensions.autodetection.enabled=falsein your ownsrc/test/resources/junit-platform.properties. - Assuming the fixtures are mutable JavaBeans.
PrimitiveTypeModelhas no setters (test/model/PrimitiveTypeModel.java:43-73) andSimpleTypeModel.invalidhas neither accessor (test/model/SimpleTypeModel.java:57). Code that introspects viajava.beansproperty descriptors will findz,b,c,s,i,l,f,dread-only there. - Binding a
Map/Collectionfield through its interface.MapTypeModel.getModels()returnsHashMapandgetModelArrays()returnsTreeMap(test/model/MapTypeModel.java:67,:75) — a consumer that resolvesMap<K,V>by interface will miss the concrete declared types used in the tests atmicrosphere-lang-model/src/test/java/io/microsphere/lang/model/util/TypeUtilsTest.java:190-193. TreeMap<PrimitiveTypeModel, …>has no usable key ordering.PrimitiveTypeModeldoes not implementComparableand overrides nothing (test/model/PrimitiveTypeModel.java:25-74), so populatingMapTypeModel.modelArrays(test/model/MapTypeModel.java:41) with a realTreeMapand putting entries requires an externalComparator. The fixture only carries the type, never an instance.- Forgetting
sinceis mandatory.test/annotation/TestAnnotation.java:69declaresSince since();with no default, so adding@TestAnnotationto your own class fails to compile until you writesince = @Since("…")— comparetest/service/TestServiceImpl.java:70. - Missing framework annotations silently. If
spring-contextis not resolved,TestServiceImpl.class.getAnnotations()simply omits@Servicerather than failing (microsphere-java-test/pom.xml:73-77). Assert on the annotations you actually declared a dependency on. @ServiceModecarries no attribute value here (test/service/TestServiceImpl.java:42), unlike the other annotations on that class. If your assertion iterates annotation member values, this one contributes none — which is a legitimate fixture case, not a bug in your code.
Tip
When adding a fixture, prefer a new type in an existing family over extending an existing type. Model,
CollectionTypeModel and friends are referenced by literal expected-value arrays in
microsphere-java-core and microsphere-lang-model; changing their shape breaks those assertions in a different
module from the one you edited.
- User guide index
- Chinese version of this page: ./module-microsphere-java-test.zh.md
- Developer guide for this module: ../developer-guide/module-microsphere-java-test.md
- microsphere-java-annotations — publishes
@Sinceand@ConfigurationProperty, the two annotations@TestAnnotationembeds (test/annotation/TestAnnotation.java:20-21,:69,:71) - microsphere-annotation-processor — the compile-time reader of
ConfigurationPropertyModel - microsphere-lang-model — the heaviest consumer of the model and service fixtures
- microsphere-jdk-tools — test-scoped consumer (
microsphere-jdk-tools/pom.xml:45-48) - Core module pages: ./microsphere-java-core/README.md