Como testar a unidade ClassLoader personalizado?

8

Por algumas razões, preciso de um filho primeiro ClassLoader. Isso ClassLoadernão existe no JDK, então estou escrevendo. Como esse é um componente-chave do meu caso de uso, eu gostaria que fosse testado intensamente. Para garantir que não seja alterado sem interromper o comportamento, quero ser extremamente completo e testar tudo o que é testável automaticamente.

Então, como posso testá-lo? Como devo fazer meu teste de unidade básico? Estou meio que confuso sobre onde começar (principalmente porque há pelo menos uma superchamada em cada método) e estou procurando algumas diretrizes para começar.

Minha idéia principal é a seguinte. Há algo de errado com isso?

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

O arquivo parent.jarcontém uma classe com.example.Exampleque é um Supplierretorno básico "parent". O arquivo child.jarcontém uma classe com.example.Exampleque é um Supplierretorno básico "child".

Eu estaria criando um padrão URLClassLoaderpara parent.jare usaria meu costume ClassLoaderpara carregar child.jar. Então eu carregava a classe com.example.Examplee verificava se ela realmente estava retornando em "child"vez de "parent".

Casos de teste mais complexos são pensados, mas eu só preciso de uma confirmação para começar: isso é suficiente para o teste básico? É realmente isso que eu deveria testar nos meus testes de unidade? Se não, o que é?


Tenho certeza de que o código não é necessário para isso, mas caso você esteja curioso ou algo assim, aqui 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
fonte
1
Sim, você tem a ideia certa. Você precisa validar que (1) para qualquer classe denominada "X", resolva X pelo carregador de classes adequado e (2) que o carregador de classes delegará todas as solicitações que não podem ser preenchidas.
Kdgregory 27/09/16
(e esta questão é, provavelmente, um melhor ajuste para SO do PSE)
kdgregory
1
No SO, eu temia que essa pergunta fosse encerrada como fora de tópico, já que é meio que pedir opinião sobre o teste adequado.
Olivier Grégoire
Sim, é triste que às vezes tenhamos medo de postar perguntas.
precisa saber é o seguinte

Respostas:

2

Então, como posso testá-lo? Como devo fazer meu teste de unidade básico? Estou meio que confuso sobre onde começar (especialmente porque há pelo menos uma chamada em cada método) e estou procurando algumas diretrizes para começar.

É verdade que não conheço muito sobre ClassLoaders ou Java, mas teria problemas ao testar isso. Um dos motivos é, como você declara, sua classe herdada URLClassLoader. Mesmo que pudéssemos zombar da superclasse de alguma forma, eu não confiaria muito nos testes para verificar se minha implementação faz o que se pretende fazer.

Então, pelo que vale a pena, gostaria de escrever um teste mais integrado aqui: talvez tenha algumas pastas "fixture" contendo exemplos como o que você apresentou:

  • Luminárias
    • CanSuccessfullyLoad
      • parent.jar
      • child.jar
    • ThrowsAnErrorOnLoad
      • justparent.jar

Isso resultaria em mim escrevendo um teste para cada um desses casos e "usando" as classes pai / filho de uma maneira muito simples, apenas para verificar se ele carregou ou falhou ao carregar como eu esperava.

user1777136
fonte