Class ClassWrapper<T>
- Type Parameters:
T- the type of the class being wrapped
- Direct Known Subclasses:
GenericClassWrapper
Abstract classes and interfaces are instantiated through a Byte Buddy subclass; concrete classes always
through their own constructor (so final classes and getClass()-based equals work).
-
Field Summary
FieldsModifier and TypeFieldDescriptionprotected TA default instance of the class for testing purposes. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedClassWrapper(Class<T> knownClass) Constructs a wrapper for a class that is already available via reflection.ClassWrapper(String expectedName, String expectedPackage, ClassWrapper<?> superClassWrapper, ClassWrapper<?>[] interfaceWrappers, String... modifiers) Constructs a new ClassWrapper with superclass and interface expectations.ClassWrapper(String expectedName, String expectedPackage, String... modifiers) Constructs a new ClassWrapper without superclass or interface expectations. -
Method Summary
Modifier and TypeMethodDescriptionReturns a string representation of the actual element signature found.booleanReturns a string representation of the expected element signature.protected voidSearches for the class in the expected package, usingLevenshteinSettings.getClassNameDeviationThreshold()for deviating names.Retrieves all AttributeWrapper fields defined in this ClassWrapper subclass.getClazz()Retrieves the actual class found via reflection.Retrieves all ConstructorWrapper fields defined in this ClassWrapper subclass.getDynamicSubclassObj(ConstructorWrapper<?> constructorWrapper, Object... constructorArgs) Creates a dynamic subclass instance using ByteBuddy for abstract classes and interfaces.Retrieves all MethodWrapper fields defined in this ClassWrapper subclass.getObj()Returns the (possibly cached) default instance of the class.abstract ObjectgetObj(boolean forceNew) Returns the default instance of the class represented by this ClassWrapper.getObj(boolean forceNew, ConstructorWrapper<?> constructorWrapper, Object... constructorArgs) Returns an instance of the class created with a specific constructor.inthashCode()protected intInterfaces are implicitlyabstract, enumsfinal(orabstractif a constant has a body), recordsfinal; nested interfaces, enums and records as well as types declared in an interface are implicitlystatic.mock()Starts aMockof the class: an object whose methods the test can replace and whose calls are recorded, created without running a constructor of the class.newObj()Creates a new default instance of the class (never cached from earlier calls).newObjOverriding(Map<MethodWrapper<?, ?>, Function<Object[], Object>> overrides) Creates an object of a subclass of the wrapped class in which each given method returns the result of its function.Creates an object of the wrapped class without running any of its constructors (attributes keep their default values0,false,null; field initializers do not run either).protected voidParses and updates the existence state based on all properties.static <V> ClassWrapper<V> Creates a wrapper that only refers to a student class by its expected name, for use as the type of an attribute, a return value or a parameter, e.g.voidsetCachedObj(Object newObj) Sets the cached default instance, e.g. to an object created in a test.voidtestGetter(AttributeWrapper<?, ?> attribute, MethodWrapper<?, ?> getter) Tests that a getter method returns the value of an attribute.voidtestGettersSetters(AttributeWrapper<?, ?> attribute, MethodWrapper<?, ?>... gettersSetters) Tests the getter and/or setter of an attribute without conditions, i.e. the setter stores every value and the getter returns the stored value.<V> voidtestGettersSetters(AttributeWrapper<?, ?> attribute, Predicate<V> setterCondition, MethodWrapper<?, ?>... gettersSetters) LiketestGettersSetters(AttributeWrapper, MethodWrapper[]), but the setter must only store values for whichsetterConditionholds.<V> voidtestGettersSetters(AttributeWrapper<?, ?> attribute, List<V> sampleValues, MethodWrapper<?, ?>... gettersSetters) LiketestGettersSetters(AttributeWrapper, MethodWrapper[]), but with own sample values instead of generated ones (required for types without generated values, e.g. own classes).<V> voidtestGettersSetters(AttributeWrapper<?, ?> attribute, List<V> sampleValues, Predicate<V> setterCondition, MethodWrapper<?, ?>... gettersSetters) CombinestestGettersSetters(AttributeWrapper, List, MethodWrapper[])(own sample values) andtestGettersSetters(AttributeWrapper, Predicate, MethodWrapper[])(setter condition).toString()Returns a string representation of this wrapped element showing its existence state.protected WrapperProperty.ExistenceA class can be used in behavioral tests as soon as it was found, even if e.g. its superclass deviates.voidverifyExistence(boolean throwAssertion) Verifies that the wrapped element exists in the actual class.voidVerifies that the actual interfaces match the expected interfaces.voidVerifies that the actual superclass matches or is compatible with the expected superclass.Methods inherited from class Wrapper
ensureChecked, getActualModifiers, getActualName, getExpectedName, getMissingModifiers, getOverallExistence, getParentClassWrapper, getUnexpectedModifiers, hasUnexpectedModifier, isModifierExpected, legacyReportsUnexpectedStatic, parseExistence, relevantModifierMask, verifyExistence, verifyModifiers
-
Field Details
-
obj
A default instance of the class for testing purposes.
-
-
Constructor Details
-
ClassWrapper
public ClassWrapper(String expectedName, String expectedPackage, ClassWrapper<?> superClassWrapper, ClassWrapper<?>[] interfaceWrappers, String... modifiers) Constructs a new ClassWrapper with superclass and interface expectations.- Parameters:
expectedName- the expected (simple or binary nested, e.g.Outer$Inner) name of the classexpectedPackage- the expected package name (""for the default package)superClassWrapper- the expected superclass wrapper (null if extends Object)interfaceWrappers- the expected interface wrappers (null or empty if none)modifiers- the expected modifiers (e.g., "public", "abstract")
-
ClassWrapper
-
ClassWrapper
Constructs a new ClassWrapper without superclass or interface expectations.- Parameters:
expectedName- the expected name of the classexpectedPackage- the expected package namemodifiers- the expected modifiers (e.g., "public", "abstract")
-
-
Method Details
-
reference
Creates a wrapper that only refers to a student class by its expected name, for use as the type of an attribute, a return value or a parameter, e.g.new AttributeWrapper<>(this, "drummer", ClassWrapper.reference("Drummer", "band"), "private"). This works even if the full wrapper of that class is not created yet (classes that refer to each other). The class is looked up like any other class (deviating names are accepted, seeLevenshteinSettings.getClassNameDeviationThreshold()), but only when the member using it is checked. The reference has no members and no default instance; it isequalto the full wrapper of the same class.- Type Parameters:
V- the type of the class- Parameters:
expectedName- the expected (simple or binary nested) name of the classexpectedPackage- the expected package name (""for the default package)- Returns:
- the reference
-
verifyExistence
public void verifyExistence(boolean throwAssertion) Description copied from class:WrapperVerifies that the wrapped element exists in the actual class. Subclasses must implement this to perform element-specific existence checks.- Specified by:
verifyExistencein classWrapper<T>- Parameters:
throwAssertion- if true, throws an AssertJ assertion failure when the element is missing. Usually set to true for behavioral tests, and false for structural tests to allow further deviation analysis.
-
implicitModifiers
protected int implicitModifiers()Interfaces are implicitlyabstract, enumsfinal(orabstractif a constant has a body), recordsfinal; nested interfaces, enums and records as well as types declared in an interface are implicitlystatic.- Overrides:
implicitModifiersin classWrapper<T>- Returns:
- the mask of implicit modifier bits
-
usability
A class can be used in behavioral tests as soon as it was found, even if e.g. its superclass deviates. -
getClazz
-
getExpectedPackage
- Returns:
- the expected package of the class
-
findWithDeviation
protected void findWithDeviation()Searches for the class in the expected package, usingLevenshteinSettings.getClassNameDeviationThreshold()for deviating names.- Specified by:
findWithDeviationin classWrapper<T>
-
verifySuperClass
public void verifySuperClass() -
verifyInterfaces
public void verifyInterfaces()Verifies that the actual interfaces match the expected interfaces. Expected interfaces are compared by the classes their wrappers resolved (so a deviating interface name still counts). An interface that is only inherited indirectly, or additional interfaces, are deviations. Updates the interfaceWrappers' existence state accordingly. -
getObj
Returns the default instance of the class represented by this ClassWrapper. Concrete wrapper subclasses implement it by callinggetObj(boolean, ConstructorWrapper, Object...)with a default constructor and arguments. Abstract classes and interfaces are instantiated through a Byte Buddy subclass, concrete classes through their own constructor.- Parameters:
forceNew- whether to force creation of a new instance instead of reusing the cached one- Returns:
- an instance of the wrapped class
-
getObj
Returns the (possibly cached) default instance of the class.- Returns:
- an instance of the wrapped class which might have been cached
-
newObj
Creates a new default instance of the class (never cached from earlier calls).- Returns:
- a new instance of the wrapped class
-
getObj
public T getObj(boolean forceNew, ConstructorWrapper<?> constructorWrapper, Object... constructorArgs) Returns an instance of the class created with a specific constructor. A cached instance is only reused if it was created with the same constructor and arguments (or set viasetCachedObj(Object)) andforceNewis false. Abstract classes and interfaces are instantiated through a Byte Buddy subclass.Pass a single array argument as
(Object) array: otherwise Java spreads an object array (e.g.String[]) into several arguments. A wrong number of arguments is reported asIllegalArgumentException.- Parameters:
forceNew- whether to force creation of a new instanceconstructorWrapper- the constructor wrapper to use for instantiation (null: no-argument constructor)constructorArgs- the arguments to pass to the constructor- Returns:
- an instance of the wrapped class
-
setCachedObj
Sets the cached default instance, e.g. to an object created in a test. It is returned bygetObj(boolean, ConstructorWrapper, Object...)untilforceNewis requested.- Parameters:
newObj- the instance to cache (null clears the cache)
-
getDynamicSubclassObj
public Object getDynamicSubclassObj(ConstructorWrapper<?> constructorWrapper, Object... constructorArgs) Creates a dynamic subclass instance using ByteBuddy for abstract classes and interfaces. This allows testing abstract classes by creating concrete implementations at runtime. Abstract methods of the instance throwAbstractMethodErrorwhen called.Pass a single array argument as
(Object) array: otherwise Java spreads an object array into several arguments. A wrong number of arguments is reported asIllegalArgumentException.- Parameters:
constructorWrapper- the constructor to imitate (null for the no-argument constructor)constructorArgs- the arguments to pass to the constructor- Returns:
- a new instance of the dynamic subclass
-
mock
Starts aMockof the class: an object whose methods the test can replace and whose calls are recorded, created without running a constructor of the class. Use it to keep tests independent, e.g. when the method under test calls another student method, or needs an object of another student class.
A missing class fails with the usual message; aMock<?> guitarist = guitaristWrapper.mock() .override(guitaristWrapper.calculateLoudness, args -> (int) args[0] * 7); Object g = guitarist.obj();finalclass, record, enum or sealed class fails with a readable message.- Returns:
- a new mock
- See Also:
-
newObjOverriding
Creates an object of a subclass of the wrapped class in which each given method returns the result of its function. No constructor of the class runs, so attributes keep their default values. Methods that are not overridden run the student's code. Same asmock().override(...)...obj(); usemock()to check the calls as well.- Parameters:
overrides- the methods to override (of this class, its superclasses or interfaces) and their functions, which get the arguments and return the result- Returns:
- the new object
- See Also:
-
newObjWithoutConstructor
Creates an object of the wrapped class without running any of its constructors (attributes keep their default values0,false,null; field initializers do not run either). A missing or broken constructor then cannot fail the test. Concrete classes (alsofinalones) are instantiated directly; abstract classes and interfaces through the subclass of aMockwithout overrides. The cached default instance (getObj()) is not changed.- Returns:
- the new object
-
getAttributeWrappers
-
getMethodWrappers
-
getConstructorWrappers
-
parseExistence
protected void parseExistence()Description copied from class:WrapperParses and updates the existence state based on all properties. Subclasses must implement this to define how to aggregate property states.- Specified by:
parseExistencein classWrapper<T>
-
expectedToString
Description copied from class:WrapperReturns a string representation of the expected element signature. Subclasses must implement this to provide element-specific formatting.- Specified by:
expectedToStringin classWrapper<T>- Returns:
- a string showing the expected element details
-
actualToString
Description copied from class:WrapperReturns a string representation of the actual element signature found. Subclasses must implement this to provide element-specific formatting.- Specified by:
actualToStringin classWrapper<T>- Returns:
- a string showing the actual element details
-
equals
-
hashCode
-
toString
Description copied from class:WrapperReturns a string representation of this wrapped element showing its existence state. The returned string is formatted to be shown to users, indicating whether the element matches exactly, deviates, is missing, or is unchecked. Reuses
Wrapper.expectedToString()andWrapper.actualToString()for representing the two states.For
WrapperProperty.Existence.EXACTmatches, shows expected (= actual) values.For
WrapperProperty.Existence.DEVIATES, shows both expected and actual values.For
WrapperProperty.Existence.MISSING, shows what was expected. -
testGetter
Tests that a getter method returns the value of an attribute. Same astestGettersSetters(AttributeWrapper, MethodWrapper[])with only a getter.- Parameters:
attribute- the attribute wrapper to testgetter- the getter method wrapper to test
-
testGettersSetters
public void testGettersSetters(AttributeWrapper<?, ?> attribute, MethodWrapper<?, ?>... gettersSetters) Tests the getter and/or setter of an attribute without conditions, i.e. the setter stores every value and the getter returns the stored value. The role of each method wrapper follows from its parameters (none: getter, one: setter). With generated sample values (at least five per type), up to three subtests run, each on a new instance: setter -> attribute, attribute -> getter (values injected via reflection) and setter -> getter. If one fails, the test fails with a message describing all three. The cached default instance (getObj()) is not changed.- Parameters:
attribute- the attribute the getter and setter belong togettersSetters- a getter (no parameters) and/or a setter (one parameter)- Throws:
IllegalArgumentException- if the method wrappers are neither one getter nor one setter
-
testGettersSetters
public <V> void testGettersSetters(AttributeWrapper<?, ?> attribute, Predicate<V> setterCondition, MethodWrapper<?, ?>... gettersSetters) LiketestGettersSetters(AttributeWrapper, MethodWrapper[]), but the setter must only store values for whichsetterConditionholds. For other values it must keep the old value or throw an exception. A condition that throws itself (e.g. aNullPointerExceptionfornull) marks the value invalid.- Type Parameters:
V- the type of values the condition is written for- Parameters:
attribute- the attribute the getter and setter belong tosetterCondition- the condition for values the setter accepts, e.g.(Double p) -> p >= 0gettersSetters- a setter (one parameter) and optionally a getter (no parameters)
-
testGettersSetters
public <V> void testGettersSetters(AttributeWrapper<?, ?> attribute, List<V> sampleValues, MethodWrapper<?, ?>... gettersSetters) LiketestGettersSetters(AttributeWrapper, MethodWrapper[]), but with own sample values instead of generated ones (required for types without generated values, e.g. own classes).- Type Parameters:
V- the type of the sample values- Parameters:
attribute- the attribute the getter and setter belong tosampleValues- the values to set (use several different ones to catch hard-coded values)gettersSetters- a getter (no parameters) and/or a setter (one parameter)
-
testGettersSetters
public <V> void testGettersSetters(AttributeWrapper<?, ?> attribute, List<V> sampleValues, Predicate<V> setterCondition, MethodWrapper<?, ?>... gettersSetters) CombinestestGettersSetters(AttributeWrapper, List, MethodWrapper[])(own sample values) andtestGettersSetters(AttributeWrapper, Predicate, MethodWrapper[])(setter condition).- Type Parameters:
V- the type of the sample values- Parameters:
attribute- the attribute the getter and setter belong tosampleValues- the values to set, valid and invalid onessetterCondition- the condition for values the setter acceptsgettersSetters- a setter (one parameter) and optionally a getter (no parameters)
-