• Horstmann Core Java, Ed 11, Vol I, Ch 5.7

## 2. Testing using reflection

### 2.1. Reflection and Testing

We use reflection quite a bit when correcting the tasks in performance assessments.

• We cannot expect that a class that the candidate should write is present.

• At the time of writing the tests it certainly is not available. We therefore have to instantiate the objects using reflection.

• Sometimes the task states the requirement of only having a specific set of field types.

• When you run the jacoco coverage plugin, jacoco itself adds so called synthetic members, which are not found in the source code of the business class, but are added by jacoco by way of instrumentation.

• We want the candidates to stick to the naming conventions.

• We want to check that a method or field has the required visibility, static-ness (`static`) or finality (`final`) or abstractness. This is defined as the set of modifiers of the member, and implemented as a simple set of bits, packed in a integer.

The following modifiers are defined:

 Modifier keyword int value Applies to 1 PUBLIC `public` 1 C, F, M PRIVATE `private` 2 C, F, M PROTECTED `protected` 4 C, F, M STATIC `static` 8 C, F, M FINAL `final` 16 C, F, M SYNCHRONIZED `synchronized` 32 M VOLATILE `volatile` 64 F TRANSIENT `transient` 128 F NATIVE `native` 256 M INTERFACE `interface` 512 C ABSTRACT `abstract` 1024 C, M STRICT `strict` 2048 C, M

Applies to means Class, Field or Method.

Note that default or package private has no modifier bits. If none of public, protected, or private is available, then that is when you get the default.

Below you see a selection of the helper methods we use to correct performance assessments.

Does the class' field name comply with the standard naming conventions?
``````/**
* Check the field definition of a class, including naming conventions.
*
* @param targetClass to check
* @param modifiers visibility, static, final
* @param type of the field
* @param fieldName of the field
* @throws SecurityException when field is not accessible.
*/
public static void checkFieldAndNaming( Class<?> targetClass,
int modifiers, Class<?> type, String fieldName )
throws SecurityException {
if ( ( PUBLIC | STATIC | FINAL ) == modifiers ) {  (1)
assertAllUpper( fieldName );
} else {                                           (2)
char firstChar = fieldName.charAt( 0 );
assertEquals( "first char not lower case", "" + (char) Character.
toLowerCase(
firstChar ), "" + (char) firstChar );
}
checkField( targetClass, modifiers, type, fieldName );
}``````
 1 Needs to be all UPPER CASE 2 Needs to start with a lower case character.
Check the modifiers on a field.
``````/**
* Check the field definition of a class.
*
* This method tests if the required modifiers are set. Example: to check
* private, but not require final, specify modifierMask == Modifier.PUBLIC |
* Modifier.PRIVATE | Modifier.PROTECTED and as modsRequired
*
* @param targetClass to check
* @param modifierMask visibility, static, final
* @param modsRequired required modifiers
* @param fieldType of the field
* @param fieldName of the field
* @throws SecurityException when field is not accessible
*/
public static void checkField( Class<?> targetClass,
int modifierMask, int modsRequired, Class<?> fieldType, String fieldName )
throws SecurityException {
Field f = null;
try {
f = targetClass.getDeclaredField( fieldName );
assertEquals( "field " + fieldName + " should be of type "
+ fieldType,
fieldType,
f.getType() );
int fieldModifiers = f.getModifiers();
if ( ( modifierMask & fieldModifiers ) != modsRequired ) {
fail( "field '" + f.getName()
+ "' should be declared '"
+ "', you declared it '"
+ Modifier.toString( fieldModifiers ) + '\'' );
}
} catch ( NoSuchFieldException ex ) {
fail( "your class '" + targetClass
+ "' does not contain the required field '"
+ " "
+ fieldType.getSimpleName()
+ " " + fieldName + "'" );
}
}``````

## 3. Week 11 exercises

Class Genealogy

Class Genealogy

Figure 1. inspiration for this task

Create a program that list the class hierarchy of class names given on the command line.

The output should be a tree like structure with Object at the top and the named class at the bottom and all intermediate super classes in between in proper order. For every level in the hierarchy, add e.g. two spaces for indentation.

To get a class object you can use Class.forName(String name) which, if the class is loadable by the JVM, is loaded.

As usual, start with writing the tests. The test class has two

1. One to show the genealogy of the Genealogy class itself.

2. One to show the class hierarchy of `javax.swing.JButton`.

The picture only show the direct lines of ancestry, not the interfaces. In this task you should show the implemented interfaces as well.

The elements that should be contained in the `javax.swing.JButton` are:

 java.lang.Object java.awt.Component java.awt.image.ImageObserver java.awt.MenuContainer java.io.Serializable java.awt.Container javax.swing.JComponent javax.swing.TransferHandler$HasGetTransferHandler javax.swing.AbstractButton java.awt.ItemSelectable javax.swing.SwingConstants javax.swing.JButton javax.accessibility.Accessible Example output for "javax.swing.JButton" ``````class hierarchy of [javax.swing.JButton] java.lang.Object java.awt.Component implements java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable java.awt.Container javax.swing.JComponent implements javax.swing.TransferHandler$HasGetTransferHandler
javax.swing.AbstractButton  implements java.awt.ItemSelectable, javax.swing.SwingConstants
javax.swing.JButton  implements javax.accessibility.Accessible``````
SQL table Generator

SQL table generator

Write an application that interprets the class definition of an entity class via reflection and spits out an SQL table definition.

The following java types and their sql counterparts should be supported. PostgreSQL types are used.

The name of the generated table should be the name of the entity class sans package name and in simple plural. Simple plural means append an 's' character to the name. Rationale: a table contains Students, plural, not student.

 Java SQL java.lang.String TEXT java.lang.Character CHAR(1) java.lang.Integer INTEGER int INTEGER java.lang.Short SMALLINT short SMALLINT java.lang.Long BIGINT long BIGINT java.math.BigDecimal DECIMAL java.math.BigInteger NUMERIC java.lang.Float REAL float REAL java.lang.Double DOUBLE PRECISION double DOUBLE PRECISION java.time.LocalDate DATE java.time.LocalDateTime TIMESTAMP

The generator should also support the following annotations on the fields of the entities.

`@Id` should generate a SERIAL or BIGSERIAL dependent on the field being a Integer or a Long and have the PRIMARY KEY attribute.
`@NotNull` should result in a `NOT NULL` constraint.
`@Check` should copy the value of the annotation as parameter to the CHECK constraint.
`@Default` should copy the value as the DEFAULT value. Quote the value where needed.

The resulting table definition should be acceptable by a postgreSQL database.

Example Module class.
``````@Data
@AllArgsConstructor
public class CourseModule {

@ID
private Integer moduleid;
@NotNull
String name;
@NotNull
@Default( value = "5" )
@Check(credits > 0)
Integer credits;

public Module( Integer moduleid, String name ) {
this( moduleid, name, 5 );
}
}``````
Example Output.
``````CREATE TABLE coursemodules (
moduleid SERIAL PRIMARY KEY,
name TEXT NOT NULL,
credits integer NOT NULL DEFAULT (5) CHECK (credits > 0)
);``````