Как заставить статический блок работать в каждом методе тестирования? - PullRequest
9 голосов
/ 26 апреля 2011

Я обнаружил, что статический блок запускается только один раз, когда я выполняю несколько тестов 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
   }
}

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

Ответы [ 5 ]

10 голосов
/ 26 апреля 2011

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

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

 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

4 голосов
/ 26 апреля 2011

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

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

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


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


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

  • Подумайте об использовании структуры внедрения зависимостей (или Inversion of Control) вместо синглетонов.

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

0 голосов
/ 20 ноября 2018

Статический блок выполняется только один раз, когда первый класс времени загружается в 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 перед созданием экземпляра автомобиля.Я должен загрузить этот класс в 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);
        }
    }
0 голосов
/ 26 апреля 2011

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

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

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

0 голосов
/ 26 апреля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...