1) Ну, я не знаю, является ли это общей схемой, но я уже использовал ее и нашел некоторые недостатки.
2) причины не делать это просто феи. Рекомендуется использовать частный аксессуар и конечный класс или метод. Если вы действительно примените более поздние версии, вы получите много повторяющихся классов для тестирования класса или метода. Кроме того, как вы можете убедиться, что кто-то из вашей команды не закончит использование пустого расширенного класса в производстве?
Мое решение этой проблемы состояло в том, чтобы использовать отражение для доступа к частным конструкторам и методам. Это как-то немного сложно, но потом это повторение. Я использую теперь мой класс отражения полезности для всех моих тестов.
Ниже мое отражение утилита класс:
import static org.junit.Assert.fail;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* The Class JunitReflectionUtils.
*/
public final class JunitReflectionUtils {
/**
* Instantiates a new junit reflection utils.
*/
private JunitReflectionUtils() {
}
/**
* Gets the method.
*
* @param givenClass_ the given class_
* @param methodName_ the method name
* @param failIfException_ if true, the method will fail
* @param parametersClass_ the parameters
* @return the method
*/
public static Method getMethod(Class<?> givenClass_, String methodName_, boolean failIfException_, Class<?> ... parametersClass_) {
Method _method = null;
try {
_method = givenClass_.getDeclaredMethod(methodName_, parametersClass_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("A method called \"" + methodName_ + "\" could not be retrieved: " + _exception.getMessage());
} else {
return null;
}
}
_method.setAccessible(true);
return _method;
}
/**
* Gets the field.
*
* @param givenClass_ the given class
* @param fieldName_ the field name
* @param failIfException_ if true then the method will fail if an exception is thrown
* @return the field
*/
public static Field getField(Class<?> givenClass_, String fieldName_, boolean failIfException_) {
Field _field = null;
try {
_field = givenClass_.getDeclaredField(fieldName_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("A field called \"" + fieldName_ + "\" could not be retrieved: " + _exception.getMessage());
} else {
return null;
}
}
_field.setAccessible(true);
return _field;
}
/**
* assign value to a field.
*
* @param field_ the given field
* @param parentObject_ the parent containing the field
* @param failIfException_ if true then the method will fail if an exception is thrown
* @param value_ the value to assign to the field
* @return the field
*/
public static boolean assignValueToField(Field field_, Object parentObject_, boolean failIfException_, Object value_) {
try {
field_.set(parentObject_, value_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("An exception has occured while setting a value to a field: " + _exception.getMessage());
}
return false;
}
return true;
}
/**
* Gets the field value from a given object.
*
* @param object_ the object
* @param fieldName_ the field name
* @param failIfException_ if true, this method will fail if an exception is thrown
* @return the field value from object
*/
public static Object getFieldValueFromObject(Object object_, String fieldName_, boolean failIfException_) {
Field _givenField = getField(object_.getClass(), fieldName_, failIfException_);
Object _returnedValue = null;
if (_givenField == null) {
return null;
} else {
try {
_returnedValue = _givenField.get(object_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("An exception has occured while retrieving a value from a field : " + _exception.getMessage());
} else {
return null;
}
}
}
return _returnedValue;
}
/**
* Gets the constructor.
*
* @param givenClass_ the given class
* @param failIfException_ if true, a fail statement will be issued when an exception is thrown
* @param parametersClasses_ the parameters classes_
* @return the constructor
*/
public static Constructor<?> getConstructor(Class<?> givenClass_, boolean failIfException_, Class<?> ... parametersClasses_) {
Constructor<?> _constructor = null;
try {
_constructor = givenClass_.getDeclaredConstructor(parametersClasses_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("The constructor from the class \"" + givenClass_.getName() + "\" could not be retrieved");
} else {
return null;
}
}
_constructor.setAccessible(true);
return _constructor;
}
/**
* Instantiante an object.
*
* @param givenClass_ the given class
* @param failIfException_ if true then a fail statement will be issued if an exception is thrown
* @param parametersClasses_ the parameters classes
* @param parameters_ the parameters
* @return the object
*/
public static Object instantianteAnObject(Class<?> givenClass_, boolean failIfException_, Class<?> [] parametersClasses_, Object... parameters_) {
Constructor<?> _constructor = getConstructor(givenClass_, failIfException_, parametersClasses_);
Object _returnedObject = null;
if (_constructor != null) {
try {
_returnedObject = _constructor.newInstance(parameters_);
} catch (Exception _exception) {
_exception.printStackTrace();
if (failIfException_) {
fail("An instance of " + givenClass_.getName() + " could not be created : " + _exception.getMessage());
} else {
return null;
}
}
}
return _returnedObject;
}
}
+1 Обычный? это вопрос стиля. Причины «не делать»? Я не вижу. – alfasin
1. Я не нашел это в своей работе, а не в здравом учебнике об модульном тестировании. 2. Вы можете протестировать свой 'private' метод, добавив различные тестовые примеры в метод' public', который выполняет этот 'private' метод. Обратите внимание, что даже если вы расширяете класс, вы не можете получить доступ к 'private' method = \. –
Я видел этот образец, используемый иногда, однако есть случаи, когда это не подходит, например. для тестирования конечных или статических методов - в этих случаях я обычно видел, как тест и реальный класс наследуются от одного и того же абстрактного суперкласса –