@Before метод в TestRule не вызывается

Я реализовал JUnit 4 TestRule (расширяя ExternalResource) и ввел его как @ClassRule в свой тестовый класс: я хочу инициализировать ресурс один раз для всех в каждом тесте этого класса и разорвать это в конечном итоге.

Моя проблема в том, что мои методы @Before и @After вообще не вызываются до/после моего метода @Test: любая идея, почему это происходит?

Минимальный компилируемый пример:

package com.acme.test;

import static org.junit.Assert.assertNull;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.ExternalResource;

class Coffee {
    public void throwAway() {}
}

class CoffeeMachine extends ExternalResource {
    Coffee whatElse;    
    @Override protected void before() throws Throwable {
        whatElse = new Coffee();
    }

    @Override protected void after() {
        whatElse.throwAway();
    }

    public Coffee gimmieCoffee() { return whatElse; }
}

public class CoffeeTester {
    @ClassRule public static CoffeeMachine CM = new CoffeeMachine();

    @Test public void drinkACoffee() {
        Coffee c = CM.gimmieCoffee();
        assertNull(c);  // ---> Coffee is null!!                       (fuuuuuuuuuu...)
    }
}

Я что-то недопонимаю здесь? Обратите внимание, что то же самое происходит с нестатическим @Rule.

Я использую JUnit 4.11.

Большое спасибо за любой намек.

Ответ 1

Я думаю, что это проблема с вашим тестировщиком. Может быть, какой-то плагин установил пользовательский бегун, который используется, когда вы запускаете свои тесты из Ecilpse?

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

enter image description here

Ответ 2

Я не вижу здесь никакой проблемы, а просто недоразумение. Прежде всего, прочитайте assert как it must be и немного измените свой код (очевидно, ваш тест говорит c must not be null, который дает нам: assertNotNull(c);

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

package com.acme.test;

import static org.junit.Assert.assertNotNull;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.ExternalResource;

class Coffee {
    public void throwAway() {}
}

class CoffeeMachine extends ExternalResource {
    Coffee whatElse;    
    @Override protected void before() throws Throwable {
        whatElse = new Coffee();
        System.out.println(" ### executing before: " + whatElse);
    }

    @Override protected void after() {
        whatElse.throwAway();
    }

    public Coffee gimmieCoffee() { return whatElse; }
}

public class CoffeeTester {
    @ClassRule public static CoffeeMachine CM = new CoffeeMachine();

    @Test public void drinkACoffee() {
        Coffee c = CM.gimmieCoffee();
        System.out.println(" ### executing test: " + c);
        assertNotNull(c); 
    }
}

Для меня это дает следующее:

 ### executing before: [email protected]
[VerboseTestNG] INVOKING: "com.acme.test.CoffeeTester" - com.acme.test.CoffeeTester.drinkACoffee()
 ### executing test: [email protected]
[VerboseTestNG] PASSED: "com.acme.test.CoffeeTester" - com.acme.test.CoffeeTester.drinkACoffee() finished in 4 ms
[VerboseTestNG] 
[VerboseTestNG] ===============================================
[VerboseTestNG]     com.acme.test.CoffeeTester
[VerboseTestNG]     Tests run: 1, Failures: 0, Skips: 0
[VerboseTestNG] ===============================================

Итак, c не является нулевым, как вы ожидаете.