Maven: mit JUnit auf Test- und Main-Classes zugreifen

jazzschmidt

Neues Mitglied
Hallo Leute!

Ich habe ein Maven Projekt, dass sich in main und test spaltet. Ich habe einen PackageImporter geschrieben, der per Reflection Klassen durchsucht und die public Methoden auf Annotationen prüft.
In einem Test (in test) rufe ich den Importer auf, der sich in main befindet. Dadurch kann ich außerhalb von test kein Package importieren. Was kann ich verändern, um es zum Laufen zu bringen?
Hier der Quelltext des PackageImporters:
Java:
package de.engram.test;


import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("rawtypes")
public class PackageImporter {

	private final String packageName;
	private final boolean recursive;
	private final String ignoreClassesRegEx;

	/**
	 * Neuen PackageImporter erstellen. Durchsucht das Package rekursiv, wenn <code>recursive</code>
	 * auf <code>true</code> gesetzt ist. <code>ignoreClassesRegEx</code> wird angegeben, um mit
	 * einem regulären Ausdruck Klassen zu ignorieren.
	 * <p>
	 * <b>Beispiel:</b><br />
	 * <code>
	 * String ignoreClassesRegEx = "Test{1}.*";<br />
	 * PackageImporter pi = new PackageImporter("de.foo.bar", true, regEx);<p />
	 * </code> Würde alle Klassen, die nicht mit "Test" beginnen aus dem Package <i>de.foo.bar</i>
	 * und der Subpackages einlesen.
	 * <p>
	 * 
	 * @param packageName der Name des Pakets, dessen Klassen eingelesen werden sollen
	 * @param ignoreClassesRegEx Klassen, die diesem regulären Ausdruck entsprechen, werden von der
	 *            Prüfung ausgenommen
	 * @param recursive gibt an, ob das Paket rekursiv durchsucht werden soll
	 */
	public PackageImporter(final String packageName, final boolean recursive, final String ignoreClassesRegEx) {
		this.packageName = packageName;
		this.recursive = recursive;
		this.ignoreClassesRegEx = ignoreClassesRegEx;
	}

	/**
	 * Neuen PackageImporter erstellen. Durchsucht das Package rekursiv, wenn <code>recursive</code>
	 * auf <code>true</code> gesetzt ist.
	 * 
	 * @see #PackageImporter(String, boolean, String)
	 * 
	 * @param packageName der Name des Pakets, dessen Klassen eingelesen werden sollen
	 * @param recursive gibt an, ob das Paket rekursiv durchsucht werden soll
	 */
	public PackageImporter(final String packageName, final boolean recursive) {
		this(packageName, recursive, "");
	}

	/**
	 * Neuen PackageImporter erstellen. Durchsucht das Package <i>nicht</i> rekursiv.
	 * 
	 * @see #PackageImporter(String, boolean, String)
	 * 
	 * @param packageName der Name des Pakets, dessen Klassen eingelesen werden sollen
	 */
	public PackageImporter(final String packageName) {
		this(packageName, false, "");
	}

	/**
	 * Importiert alle Klassen.
	 * 
	 * @return die importierten Klassen
	 */
	public List<Class> importClasses() {
		final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

		String path = packageName.replace(".", "/");
		final URL resources = classLoader.getResource(path);
		path = resources.getPath();

		final List<Class> classes = new ArrayList<Class>();
		importClassesFromDir(classes, path, 0);

		return classes;
	}

	/**
	 * Importiert rekursiv Klassen aus dem übergebenen Pfad.
	 * 
	 * @param classes die zu füllende Liste der Klassen
	 * @param path der Pfad
	 * @param directoryDepth die Pfadtiefe
	 */
	private void importClassesFromDir(final List<Class> classes, final String path, final int directoryDepth) {
		final File importDir = new File(path);
		final File[] files = importDir.listFiles();
		for (final File file : files) {
			final String absolutePath = file.getAbsolutePath();
			final int dot = absolutePath.lastIndexOf('.');
			final String extension = absolutePath.substring(dot + 1);

			if (file.isDirectory() && recursive) {
				importClassesFromDir(classes, absolutePath, directoryDepth + 1);
			} else if (file.isFile() && !file.getName().matches(ignoreClassesRegEx) && "class".equals(extension)) {
				final String packagePath = file.getParent().replace(File.separator, ".");

				String subPackage = "";
				final String fileName = file.getName();

				int index;
				int found = 0;
				char character;
				for (index = packagePath.length() - 1; found < directoryDepth; index--) {
					character = packagePath.charAt(index);
					if (character == '.') {
						found++;
					}

					subPackage = packagePath.substring(index + 1) + ".";
				}

				String filePath;
				if (directoryDepth > 0) {
					filePath = subPackage + fileName;
				} else {
					filePath = fileName;
				}

				classes.add(importFile(filePath));
			}
		}
	}

	/**
	 * Importiert die Klasse mit dem übergebenen Namen.
	 * 
	 * @param className der Klassenname
	 * @return die Klasse
	 */
	private Class importFile(final String className) {
		System.out.println("Importing " + className);
		Class clazz = null;
		try {
			clazz = Class.forName(packageName + "." + className.substring(0, className.length() - 6));
		}
		catch (final ClassNotFoundException e) {
			// In eine RuntimeException umwandeln, damit wir uns nicht kümmern müssen
			throw new RuntimeException(e.getMessage(), e);
		}
		System.out.println(clazz.getName() + " imported.");
		return clazz;
	}
}

Danke im Vorraus für jegliche Hilfe! :)
 

hexx

Mitglied
Du gehst davon aus, dass es nur eine Ressource pro Pfad gibt:

Java:
final URL resources = classLoader.getResource(path);

classLoader.getResources(path) sollte helfen.



Java:
final File importDir = new File(path);

und was machst du, wenn die Dateien in einem Jar liegen (ist ja nicht ganz unüblich)?
 

jazzschmidt

Neues Mitglied
@Noctarius
Der Test überprüft alle Klassen eines Packages auf richtig annotierte Methoden. Das sind Datenbankzugriffe, die teilweise mit transactional gekennzeichnet sind und welche, die explizit als nicht-transactional gekennzeichnet sein müssen. Ist eine Methode nicht gekennzeichnet, schlägt der Test fehl und stoppt den Build-Vorgang.

@hexx
Dankesehr! Das war die Lösung.
Die Tests werden nur für den Build-Vorgang benötigt und kommen nicht mit ins jar.
 

Ähnliche Java Themen

Neue Themen


Oben