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

Как избежать наследования в тестах JUnit?

У меня есть несколько тестовых примеров в JUnit. Все они нуждаются в том же коде, который будет выполняться в статическом методе @BeforeClass. Это дублирование кода, и я пытаюсь избавиться от него. Грязный способ сделать это - наследование. Существуют ли какие-либо другие механизмы в JUnit, которые могут помочь?

PS. Я написал это сообщение в блоге по этому вопросу: http://www.yegor256.com/2015/05/25/unit-test-scaffolding.html

4b9b3361

Ответ 1

Способ JUnit для создания многоразового кода (вместо наследования от него) - это правила.

См. https://github.com/junit-team/junit/wiki/Rules

Вот глупый образец, но вы получите смысл.

import org.junit.rules.TestRule;
import org.junit.runners.model.Statement;
import org.junit.runner.Description;

public class MyTestRule implements TestRule {
  @Override
  public Statement apply(final Statement statement, Description description) {
    return new Statement() {
      public void evaluate() throws Throwable {
        // Here is BEFORE_CODE
        try {
          statement.evaluate();
        } finally {
          // Here is AFTER_CODE
        }
      }
    };
  }
}

Затем вы можете использовать свой TestRule следующим образом:

import org.junit.Rule;

public class MyTest {
    @Rule
    public MyTestRule myRule = new MyTestRule();
}

BEFORE_CODE и AFTER_CODE будут выполняться вокруг каждого из ваших методов тестирования.

Если вам нужно запустить код только один раз для каждого класса, используйте свой TestRule как @ClassRule:

import org.junit.ClassRule;

public class MyTest {
    @ClassRule
    public static MyTestRule myRule = new MyTestRule();
}

Теперь BEFORE_CODE и AFTER_CODE будут выполняться вокруг каждого из ваших тестовых классов.

@Правило не статично, @ClassRule поле.

A @ClassRule также может быть объявлен в Suite.

Обратите внимание, что вы можете объявить несколько правил в одном тестовом классе, так как вы составляете жизненные циклы тестов в тестовых наборах, тестовых классах и уровнях тестовых методов.

Правило - это объект, который вы инициируете в своих тестовых классах (статически или нет). При необходимости вы можете добавить параметры конструктора.

НТН

Ответ 2

Если этот метод является своего рода утилитой, отделите его на другой класс со статическим методом и вызовите этот метод в @BeforeClass.

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

Ответ 3

Вы можете создать тестовый бегун

public class MyTestRunner extends BlockJUnit4ClassRunner {
  @Override
  protected Object createTest() throws Exception {
     Object test = super.createTest();
     doStuff();
  }

  public void doStuff(){
     //common code
  }
}


@RunWith(MyTestRunner.class)
public class MyTest1{
    @Test
    public void test1(){
      //test method
    }
}

Ответ 4

Статические методы не наследуются, поэтому наследование по умолчанию не является опцией. Если вы имеете в виду, что вы перемещаете метод в общий родительский класс, то это кажется плохим выбором, поскольку вы получаете только одного родителя на Java. Кажется, более подходящим является класс поддержки тестирования. Также возможно, что вы видите необходимость параметризованного теста.

Ответ 5

В этом случае нет абсолютно ничего плохого в наследовании, это на самом деле единственный способ избежать повторения этого кода в каждом подклассе. Тот факт, что методы @BeforeClass должны быть объявлены статическими в JUnit, несчастлив, но это не должно вас останавливать. Расширьте класс, и у вас есть код инициализации, который автоматически запускается для вас, не делая ничего.

Ответ 6

Если каждый класс должен иметь аннотированный метод @BeforeClass, который точно такой же, как и любой другой, то наследование не кажется мне неправильным. Если каждый из этих методов инициализации просто передает некоторый код, вы можете создать класс TestUtil с некоторым общим поведением и вызвать вызовы этого совместного поведения из каждого из методов @BeforeClass.

Ответ 7

Я думаю, что если классы имеют отношение "is-a" , наследование является разумным.

Если базовый класс MyBeforeClass, который определяет метод @BeforeClass, а MyTestClass1 "is-a" MyBeforeClass, MyTestClass1 extends MyBeforeClass в порядке.

Ответ 8

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

Ответ 9

Это тестовый код, и он не предназначен для интенсивного повторного использования. Не переусердствуйте. Не применяйте все шаблоны проектирования, которые вы знаете. Для тестового кода правила разные.