Как принудительно запустить статический блок в каждом методе тестирования?

#java #unit-testing #junit

#java #модульное тестирование #junit

Вопрос:

Я обнаружил, что статический блок запускается только один раз, когда я выполняю несколько тестов JUnit. Как я могу принудительно запустить его для каждого метода тестирования?Я использую последнюю версию JUnit 4.8.2

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

 @Test TestMethod1 () {
       Accounts ac = new Accounts();
       ac.method1(); //kill the thread inside
}

@Test TestMethod2 () {
       Accounts ac = new Accounts();
       ac.method2(); // the thread is no longer available!!
}

class Accounts {
   static {
       // initalize one thread to monitor something
   }
}
  

Это происходит даже тогда, когда TestMethod 1 и TestMethod 2 находятся в разных тестовых классах.

Комментарии:

1. если вы хотите, чтобы что-то инициализировалось перед запуском каждого @Test, сделайте это в аннотированном методе @Before

Ответ №1:

статические блоки выполняются только при загрузке класса, потому что это то, чем они являются: инициализаторами класса. Для многократного запуска статического блока потребуется выгрузка класса (что сделать непросто …).

Если вам нужно использовать статические блоки, вы можете придумать способы их тестирования. Почему бы не развернуть блок в общедоступный (статический) метод? Все, что вам нужно сделать в этом мире, это протестировать метод:

  static {
      staticInitMethod();
 }

 public static void staticInitMethod(){
      //insert initialization code here
 }
  

вы также могли бы обойтись обычным инициализатором

  {//not static
      //insert initialization code here
 }
  

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

Редактировать: Оказывается, Oracle нравится подход статического метода http://download.oracle.com/javase/tutorial/java/javaOO/initial.html

Ответ №2:

Почему статический блок выполняется только один раз?

Потому что в этом весь смысл статических блоков инициализатора!

Или, другими словами, если вы хотите, чтобы какой-либо код инициализации выполнялся несколько раз, поместите его в обычный конструктор или метод, или (в небольшом числе случаев) нестатический блок инициализатора.


В контексте JUnit обычный способ реализации кода запуска и завершения тестирования с использованием методов setUp() и tearDown() .


Если вы пытаетесь модульно протестировать выполнение статической инициализации в своем собственном коде, я думаю, вас ждет нелегкий путь. Но тогда модульное тестирование кода со статическим состоянием (например, одиночных элементов) всегда затруднено … и это одна из причин, по которой люди думают, что статическое состояние — плохая идея.

  • Рассмотрите возможность использования фреймворка внедрения зависимостей (он же инверсия управления) вместо одиночек.

  • В качестве альтернативы, рассмотрите возможность изменения вашего кода одиночной / статической инициализации, чтобы упростить тестирование. Например, добавьте статический метод, который позволяет тесту повторно выполнить инициализацию. (И прежде чем вы скажете, что это нарушает шаблон singleton: да, я знаю. Вам нужно выбирать между «чистотой» дизайна / реализации и простотой тестирования.)

Комментарии:

1. Но в Junit framework каждый метод тестирования должен быть полностью независимым от другого?

2. Каждый тестовый класс JUnit может иметь свой собственный startup() и shutdown() . Если вы хотите, чтобы методы тестирования были полностью независимыми, вы могли бы поместить каждый из них в свой собственный класс.

3. @Stephen, одноэлементный шаблон полезен время от времени.

4. ДА… но это также создает серьезные проблемы для модульного тестирования. Многие люди думают, что внедрение зависимостей предлагает более чистую альтернативу синглетам. Это ваш выбор, но на тестируемость влияет этот выбор. Вы не можете использовать оба способа…

5. @user: Если вы имеете дело с синглтоном, то вам следовало так и сказать.

Ответ №3:

Является ли статический код для тестов для тестируемого класса?

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

Если вы хотите, чтобы каждый тест был автономным, затем переместите то, что вы делаете в своем статическом блоке, в методы setup () / teardown (), для этого они и существуют.

Ответ №4:

Статический блок выполняется только один раз при первой загрузке класса в JVM. Junit предоставляет @Before аннотацию, которая в основном используется для требуемой инициализации тестового примера. Это может быть использовано для выполнения статических блоков класса. например, у меня есть следующий класс Car

     public class Car implements Vehicle{

        private String type = "lmv";    
        static {            
            VehicleFactoryWithoutRefl.getInstance().registerVehicle("car", new Car());
        }
        @Override
        public void moveForward() {
        }

        @Override
        public String getType() {
            return type;
        }

        @Override
        public Vehicle createVehicle() {
            return new Car();
        }



    }
  

и я хочу выполнить статический блок этого класса в Junit перед созданием экземпляра car. Я должен загрузить этот класс в, setUp() используя class.forName("package.ClassName") код Junit.

   public class TestFactory {

        @Before
        public void setUp() {
            try {
                Class.forName("com.cg.dp.factory.Car");
            } catch (ClassNotFoundException e) {
                //e.printStackTrace();
            }
        }

        @Test
        //@Ignore
        public void testFactoryInstanceWithoutRefl() {
            Vehicle v1 = VehicleFactoryWithoutRefl.getInstance().newVehicle("car");
            assertTrue(v1 instanceof Car);
        }
    }
  

Ответ №5:

Хм … сделать его нестатическим? У вас также могут быть блоки инициализатора экземпляра (такие же, как статические блоки, только без static ключевого слова). Но код настройки теста на самом деле должен входить в явный метод setUp() or @Before .

Комментарии:

1. Я думаю, что смысл здесь в том, чтобы протестировать статическую инициализацию через JUnit, а не перепроектировать тестируемый класс. Итак, докажите, что каждый статический метод при первом вызове (и, следовательно, загрузке класса и вызове статической инициализации) работает корректно. Хотя это может быть и неправильно.

2. Мне нужно иметь статический блок, чтобы убедиться, что все объекты имеют некоторые общие черты.

3. @user — ты не обязан . Есть и другие способы поделиться общими вещами.