JUnit 4: настроить вещи в наборе тестов до запуска тестов (например, метод testBeforeClass, только для набора тестов)

Я хочу провести некоторое функциональное тестирование на (спокойном) веб-сервисе. Testuite содержит кучу тестовых примеров, каждый из которых выполняет пару HTTP-запросов в веб-сервисе.

Естественно, веб-сервис должен запускаться или тесты будут терпеть неудачу.: -)

Запуск web-сервиса занимает пару минут (он делает некоторые тяжелые подъемы данных), поэтому я хочу начать его как можно реже (по крайней мере, все тестовые примеры, которые могут использовать только ресурсы GET из службы).

Итак, есть ли способ установить бомбу в тестовом наборе, прежде чем тесты будут запущены, как в методе @BeforeClass тестового примера?

Ответ 1

Теперь ответ должен создать @ClassRule в вашем пакете. Правило будет вызываться до или после (в зависимости от того, как вы его реализуете) запускается каждый тестовый класс. Существует несколько различных базовых классов, которые вы можете расширить/реализовать. Что приятно в правилах классов, так это то, что если вы не реализуете их как анонимные классы, вы можете повторно использовать код!

Вот статья о них: http://java.dzone.com/articles/junit-49-class-and-suite-level-rules

Вот пример кода, иллюстрирующий их использование. Да, это тривиально, но это должно хорошо иллюстрировать жизненный цикл, чтобы вы начали.

Сначала определение пакета:

import org.junit.*;
import org.junit.rules.ExternalResource;
import org.junit.runners.Suite;
import org.junit.runner.RunWith;


@RunWith( Suite.class )
@Suite.SuiteClasses( { 
    RuleTest.class,
} )
public class RuleSuite{

    private static int bCount = 0;
    private static int aCount = 0;

    @ClassRule
    public static ExternalResource testRule = new ExternalResource(){
            @Override
            protected void before() throws Throwable{
                System.err.println( "before test class: " + ++bCount );
                sss = "asdf";
            };

            @Override
            protected void after(){
                System.err.println( "after test class: " + ++aCount );
            };
        };


    public static String sss;
}

И теперь определение тестового класса:

import static org.junit.Assert.*;

import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExternalResource;

public class RuleTest {

    @Test
    public void asdf1(){
        assertNotNull( "A value should've been set by a rule.", RuleSuite.sss );
    }

    @Test
    public void asdf2(){
        assertEquals( "This value should be set by the rule.", "asdf", RuleSuite.sss );
    }
}

Ответ 2

jUnit не может этого делать, хотя TestNG имеет аннотации @BeforeSuite и @AfterSuite. Как правило, вы получаете свою систему сборки для этого. В maven существуют фазы "pre-integration-test" и "post-integration-test". В ANT, вы просто добавляете шаги к задаче.

Ваш вопрос в значительной степени похож на до и после завершения выполнения пакета в jUnit 4.x, поэтому я взглянул на предложения там.

Ответ 3

Один из вариантов - использовать что-то вроде Apache Ant для запуска вашего пакета unit test. Затем вы можете поместить целевой вызов до и после цели junit для запуска и остановки вашего веб-сервиса:

<target name="start.webservice"><!-- starts the webservice... --></target>
<target name="stop.webservice"><!-- stops the webservice... --></target>
<target name="unit.test"><!-- just runs the tests... --></target>

<target name="run.test.suite" 
        depends="start.webservice, unit.test, stop.webservice"/>

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

Ответ 4

В стороне, это плохая идея иметь модульные тесты, фактически вызывающие внешние ресурсы, такие как webservices, базы данных и т.д.

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

Мой совет:

Посмотрите на насмешливые внешние зависимости в модульных тестах с чем-то вроде EasyMock (http://www.easymock.org/).

Создайте отдельный набор интеграционных тестов с чем-то вроде Fitnesse (http://fitnesse.org/) или домашнее решение, которое работает против тестовой среды и который постоянно растет.