web-dev-qa-db-fra.com

Test de la classe ClassNotFoundException

J'essaie de tester qu'une classe ne se trouve pas avec UnitTest sur Android. 

Que se passe-t-il:
1. J'écris une bibliothèque Android avec des dépendances transitive qui sont résolues dans l'application hôte.
2. Le développeur peut supprimer certaines dépendances, par exemple supprimer tout com.example.package
3. J'ai une usine qui essaie d'instancier (en utilisant la réflexion) un objet et d'attraper le ClassNotFoundException. Si le développeur supprime les dépendances, l'exception doit être levée.
4. Je veux tester ce cas, mais tout ce que j'ai trouvé est un problème avec les dépendances, pas comment le tester. 

Exemple de code que je veux tester  

try {
    sNetworkResponseBuilderClass = OkHttpNetworkResponse.Builder.class;
} catch (Exception e){
    // <<<< I want to test this case
    new ClassNotFoundException("Unable to find OkHttpNetworkResponse.Builder.class").printStackTrace();
    return null;
}

bibliothèque utilisée: hamcrast, mockito, JUnit 4. 

Savez-vous comment le faire?

19
Hugo Gresse

Donc, pour moi, la première chose à faire est d’extraire la partie du code qui peut lancer une ClassNotFoundException afin de pouvoir la simuler facilement, quelque chose comme:

public Class<? extends NetworkResponseBuilder> getNetworkResponseBuilderClass()
    throws ClassNotFoundException {
    // Your logic here
}

Ensuite, vous pouvez tester une instance de fabrique réelle en utilisant Mockito.spy pour pouvoir redéfinir le comportement de la méthode getNetworkResponseBuilderClass() comme suit:

public void testFactoryIfNetworkResponseBuilderNotFound() {
    Factory factory = spy(new Factory());
    when(factory.getNetworkResponseBuilderClass()).thenThrow(
        new ClassNotFoundException()
    );
    // The rest of your test here
}

public void testFactoryIfNetworkResponseBuilderFound() {
    Factory factory = spy(new Factory());
    when(factory.getNetworkResponseBuilderClass()).thenReturn(
        OkHttpNetworkResponse.Builder.class
    );
    // The rest of your test here
}

Plus de détails sur Mockito.spy .

10
Nicolas Filotto

Pas tout à fait sûr d'avoir bien compris votre question, mais vous pouvez vérifier avec JUnit si une exception est levée

@Test(expected=ClassNotFoundException.class)
public void testClassNotFoundException() {
    // a case where the exception gets thrown
}
6
Christoph

OkHttpNetworkResponse.Builder pourrait être comme suit:

package com.example.model;

public class OkHttpNetworkResponse {
    public static class Builder {

    }
}
  1. J'ai une fabrique qui essaiera d'instancier (en utilisant la réflexion) un objet et de capturer la ClassNotFoundException. Si le développeur supprime les dépendances, l'exception devrait être levée.

Classe d'usine: qui créera n'importe quel objet pourrait être comme suit:

package com.example.factory;

public class Factory {
    public static Object getInstance(String className)
            throws ClassNotFoundException, InstantiationException,
            IllegalAccessException {
        Class clazz = Class.forName(className);
        return clazz.newInstance();
    }
}
  1. Le développeur peut supprimer certaines dépendances, par exemple supprimer tous les com.example.package.
  2. Je veux tester ce cas, mais tout ce que j'ai trouvé est un problème avec les dépendances, pas comment le tester.

Classe FactoryTest: qui permettra de vérifier si une exception ClassNotFoundException est levée ou non: N.B: veuillez vérifier les commentaires attentivement.

package com.example.factory;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import Java.io.File;
import Java.io.IOException;

import org.junit.Test;

public class FactoryTest {
    Factory factory;

    @Test(expected=ClassNotFoundException.class)
    public void test() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        ClassLoader loader = FactoryTest.class.getClassLoader();
        String directory = loader.getResource(".").getPath() + "/com/example/model";
        File dir = new File(directory);
        //Checking directory already existed or not..
        assertTrue("Directory:"+dir.getPath()+" not exist",dir.exists());
          //Deleting directory 
        deleteDirectoryProgramatically(directory);
        //Checking directory already deleted or not..
        assertFalse("Directory:"+dir.getPath()+" still exist",dir.exists());
        //Now getInstance Method will throw ClassNotFoundException because OkHttpNetworkResponse.Builder.class has been deleted programatically. 
        Factory.getInstance("OkHttpNetworkResponse.Builder.class");
    }

    private void deleteDirectoryProgramatically(String directory) {
        File dir = new File(directory);
        System.out.println(dir.getAbsolutePath());
        String[] files = dir.list();
        for (String f : files) {
            File fl = new File(directory,f);
            System.out.println(f+ " deleted?"+fl.delete());
        }
        System.out.println(dir+ " deleted?"+dir.delete());
    }
}
3
CrawlingKid

C'est une question très simple. Le test d'unité d'exception JUnit4 est donné ci-dessous avec un exemple. J'espère que cela vous éclaircira.

MyNumber.Java

public class MyNumber {
   int number;
   public MyNumber div(MyNumber rhs) {
      if (rhs.number == 0) throw new IllegalArgumentException("Cannot divide by 0!");
      this.number /= rhs.number;
      return this;
   }
}

MyNumberTest.Java

public class MyNumberTest {
   private MyNumber number1, number2; // Test fixtures
   @Test(expected = IllegalArgumentException.class)
   public void testDivByZero() {
      System.out.println("Run @Test testDivByZero"); // for illustration
      number2.setNumber(0);
      number1.div(number2);
   }
}

JUnit - Test d'exceptions

Pour vérifier si le code génère une exception souhaitée, utilisez l'annotation @Test(expected = exception.class), comme illustré dans l'exemple précédent. Pour votre cas ce sera

/**
* Check for class not found exception
**/
@Test(expected=ClassNotFoundException.class)
public void testClassNotFoundException() {
    .....
}

Pour une meilleure compréhension, vous pouvez suivre ce tutoriel: Java Unit Tests - JUnit & TestNG . Il contient un exemple complet de code en cours d'exécution étape par étape avec des explications.

2
SkyWalker

dans catch, vous pouvez vérifier l'objet avec l'opérateur instanceof comme suit:

try {
    sNetworkResponseBuilderClass = OkHttpNetworkResponse.Builder.class;
} catch (Exception e){
    if(e instanceof ClassNotFoundException){
        // here you can do the code you want in case of ClassNotFoundException thrown
    }
}
0
Pankaj Verma

c'est votre problème de dictionnaire. dans votre dictionnaire en classe de test n'aura pas. change ton dictionnaire.

0
Idrish Multani

Utilisez Class.forName ("com.example.ClassName")

try {
 Class.forName("com.example.OkHttpNetworkResponse.Builder");
} catch (ClassNotFoundException e) {
  // This class was not found
}

Voir Class.forName (String className)

0
Luis