JUnit Tests und Reflection
Mit Hilfe von Java Reflection lassen sich grosse POJO Objekte unter JUnit einfach Vergleichen.
Angenommen man hat ein einfaches POJO Objekt Metadata mit einigen Attributen:
public class Metadata {
private Integer id;
private String filename;
private Integer height;
private Integer width;
private long fileSize;
private String fileFormat;
private String comment;
// and some more attributes
/**
* Getter and Setter-Methods
*/
}
Es werden nie alle Attribute gleichzeitig gefüllt, sondern je nach Prozessschritt immer nur ein paar. Zum Beispiel beim Einlesen der Datei können Breite, Höhe, Dateiname und Dateigröße gesetzt werden. Alle anderen Attribute sollen nicht gefüllt werden. Um sicherzustellen, dass beim Einlesen der Datei auch keine weiteren Attribute gesetzt werden, muss im Test abgefragt werden, ob alle anderen Attribute auch NULL sind.
@Test
public void testReadFileMetadata() {
Metadata meta = new Metadata();
File file = new File("someTestFile.jpg");
// Metadata attributes will be read and set
foo.readFileMetadata(meta, file);
// now test if attributes were set correct
assertEquals("someTestFile.jpg", meta.getFileName());
// ... go on with height, width and size
// all other attributes should still be NULL
assertNull(meta.getFileFormat());
assertNull(meta.getId);
assertNull(meta.getComment);
}
Die Id wird dem Metaobjekt zum Beispiel über eine Datenbank hinzugefügt. Hierzu gibt es eine eigene Methode createMetaId():
public void createMetaId(Metadata meta) {
// set up database stuff
Integer id = database.getNextId();
meta.setId(id)
}
Für einen vollständigen Test, müssten auch hier wieder alle Attribute abgefragt werden:
@Test
public void testCreateMetaId() {
Metadata meta = new Metadata();
dbTier.createMetaId(meta);
assertEquals(123456, meta.getId()):
// test if all other attributes are NULL
assertNull(meta.getFileFormat());
// ...
assertNull(meta.getComment);
}
Unter Verwendung von Reflection kann man bei den Tests sich eine Menge an Code sparen:
public class ReflectionComparator {
public static void compareObjects(Object expected, Object actual) {
try {
for(Field field : expected.getClass().getDeclaredFields()) {
// setAccessible == true will allow to access private fields
field.setAccessible(true);
assertEquals(field.get(expected), field.get(actual));
}
} catch(Exception e) {
fail(e.getMessage());
}
}
}
Die Tests angepasst mit der Klasse ReflectionComparator sehen wie folgend aus:
@Test
public void testReadFileMetadata() {
Metadata metaActual = new Metadata();
File file = new File("someTestFile.jpg");
// Metadata attributes will be read and set
foo.readFileMetadata(metaActual, file);
// create new object Metadata and set the expected attributes
Metadata metaExpected = new Metadata();
metaExpected.setFileName("someTestFile.jpg");
// ... go on with setters for height, width and size
// compare metaExpected with metaActual
ReflectionComparator.compareObjects(metaExpected, metaAcutal);
}
@Test
public void testCreateMetaId() {
Metadata metaActual = new Metadata();
dbTier.createMetaId(metaActual);
Metadata metaExpected = new Metadata();
metaExpected.setId(123456);
// compare metaExpected with metaActual
ReflectionComparator.compareObjects(metaExpected, metaAcutal);
}
Damit hat man sich jede Menge an Testcode gespart und überprüft zusätzlich alle Attribute eines Objektes, ob diese gleich sind.