Тестирование ClassNotFound Exception

Я пытаюсь проверить, что класс не найден с UnitTest на Android.

Что происходит:
1. Я пишу библиотеку андроида с transitive зависимостями, которые разрешены в хост-приложении
2. Разработчик может удалить некоторые зависимости, например, удалить все com.example.package
3. У меня есть Factory, который попытается создать экземпляр (используя отражение) объекта и поймать ClassNotFoundException . Если разработчик удаляет зависимости, следует исключить исключение.
4. Я хочу проверить этот случай, но все, что я нашел, это проблема с зависимостями, а не как проверить его.

Пример кода, который я хочу проверить

 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; } 

Используемая библиотека: hamcrast, mockito, JUnit 4.

Вы знаете, как это сделать?

Поэтому для меня первое, что вам нужно сделать, – это извлечь часть кода, которая может вызвать ClassNotFoundException , чтобы иметь возможность легко издеваться над ней, например:

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

Затем вы можете протестировать настоящий заводский экземпляр с использованием Mockito.spy чтобы иметь возможность переопределить поведение метода getNetworkResponseBuilderClass() следующим образом:

 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 } 

Подробнее о Mockito.spy .

Не совсем уверен, правильно ли я понял ваш вопрос, но вы можете проверить JUnit, если будет выбрано исключение:

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

OkHttpNetworkResponse.Builder может быть следующим:

 package com.example.model; public class OkHttpNetworkResponse { public static class Builder { } } 
  1. У меня есть Factory, который попытается создать экземпляр (используя отражение) объекта и поймать ClassNotFoundException. Если разработчик удаляет зависимости, следует исключить исключение.

Фабричный класс: который создаст любой объект, может быть следующим:

 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. Разработчик может удалить некоторые зависимости, например, удалить все com.example.package
  2. Я хочу проверить этот случай, но все, что я нашел, это проблема с зависимостями, а не как проверить его.

FactoryTest Class: проверяет, выбрано ли ClassNotFoundException или нет, может быть следующим: NB: пожалуйста, внимательно просмотрите комментарии.

 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()); } } 

Это очень простая проблема. Тестирование модуля исключения JUnit4 приведено ниже с примером. Надеюсь, это прояснит вас.

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(expected = exception.class) ли код желаемое исключение, используйте аннотацию @Test(expected = exception.class) , как показано в предыдущем примере. Для вашего дела это будет

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

Для лучшего понимания вы можете ознакомиться с этим руководством: Java Unit Testing – JUnit & TestNG . Он содержит полный пример кода запуска поэтапно с объяснением.

Внутри catch вы можете проверить объект с помощью оператора instanceof как:

 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 } } 

Это ваша проблема с словарем. В вашем словаре в тестовом классе не будет. Измените словарь.

Используйте Class.forName ("com.example.ClassName")

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

См. Class.forName (String className)