2013-06-27 1 views
2

В answer на вопрос, который я просил, мне посоветовали решить конкретную (ненужную) задачу, сделав класс (test_C), предназначенный для проверки основного класса (C) является дочерний класс С:Является ли это распространенным/приемлемым шаблоном в Java-разработке для тестового класса для расширения тестируемого класса?

public class test_C extends C { 
  1. Это общий шаблон в Java-разработке?

  2. Есть ли причины не использовать этот шаблон для всех тестовых классов (предположим, что мы всегда имеем сопоставление 1-1 между тестовым классом и тестированным классом)?

+0

+1 Обычный? это вопрос стиля. Причины «не делать»? Я не вижу. – alfasin

+0

1. Я не нашел это в своей работе, а не в здравом учебнике об модульном тестировании. 2. Вы можете протестировать свой 'private' метод, добавив различные тестовые примеры в метод' public', который выполняет этот 'private' метод. Обратите внимание, что даже если вы расширяете класс, вы не можете получить доступ к 'private' method = \. –

+0

Я видел этот образец, используемый иногда, однако есть случаи, когда это не подходит, например. для тестирования конечных или статических методов - в этих случаях я обычно видел, как тест и реальный класс наследуются от одного и того же абстрактного суперкласса –

ответ

3

Есть ли какие-либо причины не использовать этот шаблон для всех тестовых классов (предположим, что у нас всегда есть 1-1 соответствие между тестовым классом и испытания класс)?

Испытываемый класс может быть окончательным, не позволяя любому классу подклассифицировать его.

public final class C { ... } 

Если тестирование подкласса является возможно, это могло бы изменить поведение класса тестируется - неумышленно, а также преднамеренно.

1

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


} 
+0

Как вы можете убедиться в том, что кто-то из вашей команды не закончит использование расширенного класса фиктивного класса? Использование префикса имени класса «UniTest» должно легко решить эту проблему. – DVK