¿Cómo probar un ClassLoader personalizado?

8

Por alguna razón, necesito un hijo primero ClassLoader. Tal ClassLoaderno existe en el JDK, así que lo estoy escribiendo. Dado que este es un componente clave de mi caso de uso, me gustaría que fuera sometido a pruebas exhaustivas. Para garantizar que no se cambie sin romper el comportamiento, quiero ser extremadamente minucioso y probar todo lo que se pueda probar automáticamente.

Entonces, ¿cómo puedo probarlo? ¿Cómo debo hacer mi prueba de unidad básica? Estoy atascado en cuanto a dónde comenzar (especialmente porque hay al menos una superllamada en cada método) y estoy buscando algunas pautas para comenzar.

Mi idea principal es la siguiente. ¿Hay algo malo en ello?

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

El archivo parent.jarcontiene una clase com.example.Exampleque es un Supplierretorno básico "parent". El archivo child.jarcontiene una clase com.example.Exampleque es un Supplierretorno básico "child".

Estaría creando un estándar URLClassLoaderpara parent.jar, y usaría mi costumbre ClassLoaderpara cargar child.jar. Luego cargaría la clase com.example.Exampley verificaría que en realidad regrese en "child"lugar de "parent".

Se piensan casos de prueba más complejos, pero solo necesito una confirmación para comenzar: ¿es esto suficiente para la prueba básica? ¿Es esto realmente lo que debería probar en mis pruebas unitarias? Si no, ¿qué es?


Estoy bastante seguro de que el código no es necesario para esto, pero en caso de que tenga curiosidad o lo que sea, aquí está.

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
fuente
1
Sí, tienes la idea correcta. Debe validar que (1) para cualquier clase llamada "X" resuelva X mediante el cargador de clases adecuado y (2) que el cargador de clases delegará cualquier solicitud que no pueda completar.
kdgregory
(y esta pregunta probablemente sea más adecuada para SO que para PSE)
kdgregory
1
En SO, temía que esta pregunta se cerrara como fuera de tema, ya que es una especie de opinión sobre las pruebas adecuadas.
Olivier Grégoire
Sí, triste que a veces nos da miedo publicar preguntas.
djangofan

Respuestas:

2

Entonces, ¿cómo puedo probarlo? ¿Cómo debo hacer mi prueba de unidad básica? Estoy atascado en cuanto a dónde comenzar (especialmente porque hay al menos una súper llamada en cada método) y estoy buscando algunas pautas para comenzar.

Por supuesto, no sé mucho sobre ClassLoaders o Java para ese asunto, pero tendría problemas para que la unidad lo pruebe. Una de las razones es, como usted dice, que su clase hereda de URLClassLoader. Incluso si pudiéramos burlarnos de la superclase de alguna manera, no confiaría mucho en las pruebas que verifican que mi implementación hace lo que se pretende hacer.

Entonces, para lo que vale, me inclinaría por escribir una prueba más integrada aquí: tal vez tener algunas carpetas "fixture" que contengan ejemplos como el que usted presentó:

  • Accesorios
    • CanSuccessfullyLoad
      • parent.jar
      • niño.jar
    • ThrowsAnErrorOnLoad
      • justparent.jar

Eso me llevaría a escribir una prueba para cada uno de esos casos y "usar" las clases padre / hijo de una manera muy simple solo para verificar que se cargó o no se pudo cargar como esperaba.

usuario1777136
fuente