Подтвердить что ты не робот

Тестирование 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.

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

4b9b3361

Ответ 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 {

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

Класс 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)