Wie teste ich einen benutzerdefinierten ClassLoader?

8

Aus bestimmten Gründen brauche ich zuerst ein Kind ClassLoader. Solches ClassLoadergibt es im JDK nicht, also schreibe ich es. Da dies eine Schlüsselkomponente meines Anwendungsfalls ist, möchte ich, dass er intensiv getestet wird. Um sicherzustellen, dass es nicht geändert wird, ohne das Verhalten zu beeinträchtigen, möchte ich äußerst gründlich sein und alles testen, was automatisch getestet werden kann.

Wie kann ich es testen? Wie soll ich meinen Basis-Unit-Test machen? Ich bin mir nicht sicher, wo ich anfangen soll (zumal es superin jeder Methode mindestens einen Aufruf gibt) und suche nach Richtlinien, um zu beginnen.

Meine Hauptidee ist die folgende. Stimmt etwas nicht?

/src/main/resources/parent.jar
                    child.jar

Die Datei parent.jarenthält eine Klasse, com.example.Exampledie eine grundlegende SupplierRückgabe darstellt "parent". Die Datei child.jarenthält eine Klasse, com.example.Exampledie eine grundlegende SupplierRückgabe darstellt "child".

Ich würde einen Standard URLClassLoaderfür erstellen parent.jarund meine Gewohnheit ClassLoaderzum Laden verwenden child.jar. Dann würde ich die Klasse laden com.example.Exampleund überprüfen, ob sie tatsächlich zurückkehrt, "child"anstatt "parent".

Über komplexere Testfälle wird nachgedacht, aber ich brauche nur eine Bestätigung, um zu beginnen: Reicht dies für den Basistest aus? Sollte ich das wirklich in meinen Unit-Tests testen? Wenn nicht, was ist das?


Ich bin mir ziemlich sicher, dass der Code dafür nicht benötigt wird, aber falls Sie neugierig sind oder was auch immer, hier ist es.

import java.io.*;
import java.net.*;
import java.util.*;

class ChildFirstClassLoader extends URLClassLoader {

  ChildFirstClassLoader(ClassLoader parent) {
    super(new URL[0], parent);
  }

  @Override
  // Make this method available in this package.
  protected void addURL(URL url) {
    super.addURL(url);
  }

  @Override
  protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    synchronized (getClassLoadingLock(name)) {
      Class<?> c = findLoadedClass(name);
      if (c == null) {
        try {
          c = findClass(name);
        } catch (ClassNotFoundException ignore) {
          c = super.loadClass(name, resolve);
        }
      }
      if (resolve) {
        resolveClass(c);
      }
      return c;
    }
  }

  @Override
  public URL getResource(String name) {
    URL url = findResource(name);
    if (url == null) {
      url = super.getResource(name);
    }
    return url;
  }

  @Override
  public Enumeration<URL> getResources(String name) throws IOException {
    List<URL> urls = new ArrayList<>();
    urls.addAll(Collections.list(findResources(name)));
    urls.addAll(Collections.list(super.getResources(name)));
    return Collections.enumeration(urls);
  }
}
Olivier Grégoire
quelle
1
Ja, du hast die richtige Idee. Sie müssen überprüfen, dass (1) für jede Klasse mit dem Namen "X" Sie X durch den richtigen Klassenlader auflösen und (2) dass der Klassenlader alle Anforderungen delegiert, die er nicht erfüllen kann.
kdgregory
(und diese Frage passt wahrscheinlich besser zu SO als zu PSE)
kdgregory
1
Bei SO befürchtete ich, dass diese Frage als nicht zum Thema gehörend geschlossen wird, da sie eine Art Meinung zu ordnungsgemäßen Tests einholt.
Olivier Grégoire
Ja, traurig, dass wir manchmal Angst haben, Fragen zu stellen.
Djangofan

Antworten:

2

Wie kann ich es testen? Wie soll ich meinen Basis-Unit-Test machen? Ich bin mir nicht sicher, wo ich anfangen soll (zumal es in jeder Methode mindestens einen Superaufruf gibt), und ich suche nach Richtlinien, um zu beginnen.

Zugegeben, ich weiß nicht viel über ClassLoaders oder Java, aber ich hätte Probleme, dies zu testen. Einer der Gründe ist, wie Sie sagen, dass Ihre Klasse von erbt URLClassLoader. Selbst wenn wir die Oberklasse irgendwie verspotten könnten, hätte ich nicht viel Vertrauen in die Tests, die bestätigen, dass meine Implementierung das tut, was beabsichtigt ist.

Für das, was es wert ist, würde ich mich darauf stützen, hier einen stärker integrierten Test zu schreiben: Vielleicht ein paar "Fixture" -Ordner mit Beispielen wie dem, den Sie vorgestellt haben:

  • Vorrichtungen
    • CanSuccessfullyLoad
      • parent.jar
      • child.jar
    • ThrowsAnErrorOnLoad
      • justparent.jar

Das würde dazu führen, dass ich für jeden dieser Fälle einen Test schreibe und die Eltern / Kind-Klassen auf sehr einfache Weise "verwende", um zu überprüfen, ob sie geladen wurden oder nicht wie erwartet geladen wurden.

user1777136
quelle