Тестирование 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.
Вы знаете, как это сделать?
Ответы
Ответ 1
Итак, для меня первое, что вам нужно сделать, это извлечь часть кода, которая может выбросить ClassNotFoundException
, чтобы быть в состоянии легко издеваться над ней, например:
public Class<? extends NetworkResponseBuilder> getNetworkResponseBuilderClass()
throws ClassNotFoundException {
// Your logic here
}
Затем вы можете протестировать реальный экземпляр factory с помощью 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.
Ответ 2
Не совсем уверен, правильно ли я понял ваш вопрос, но вы можете проверить с помощью JUnit, если будет выбрано исключение:
@Test(expected=ClassNotFoundException.class)
public void testClassNotFoundException() {
// a case where the exception gets thrown
}
Ответ 3
OkHttpNetworkResponse.Builder может быть следующим:
package com.example.model;
public class OkHttpNetworkResponse {
public static class Builder {
}
}
- У меня есть Factory, который попытается создать экземпляр (используя отражение) объекта и поймать ClassNotFoundException. Если разработчик удалит зависимостей, следует исключить исключение.
Factory Класс:, который создаст любой объект, может быть следующим:
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();
}
}
- Разработчик может удалить некоторые зависимости, например, удалить все com.example.package
- Я хочу проверить этот случай, но все, что я нашел, это проблема с зависимостями, а не как проверить его.
Класс FactoryTest:, который будет проверять, выбрано ли ClassNotFoundException или нет, может быть следующим: N.B: пожалуйста, внимательно просмотрите комментарии.
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());
}
}
Ответ 4
Это очень простая проблема. Тестирование модуля исключения 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)
, как показано в предыдущем примере. Для вашего случая это будет
/**
* Check for class not found exception
**/
@Test(expected=ClassNotFoundException.class)
public void testClassNotFoundException() {
.....
}
Для лучшего понимания вы можете пройти этот учебник: Java Unit Тестирование - JUnit и TestNG. Он содержит пример полного запуска кода шаг за шагом с объяснением.
Ответ 5
внутри 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
}
}
Ответ 6
это проблема со словарем. в вашем словаре в тестовом классе не будет. измените словарь.
Ответ 7
Используйте Class.forName( "com.example.ClassName" )
try {
Class.forName("com.example.OkHttpNetworkResponse.Builder");
} catch (ClassNotFoundException e) {
// This class was not found
}
См. Class.forName(String className)