JUnit @BeforeClass нестатический работает для Spring загрузочного приложения

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

Я хочу очистить базу данных, чтобы я @Autowire с помощью Spring Boot, один раз, прежде чем запускать тесты JUnit. Я не могу @Autowire статические поля, поэтому мне нужно подумать о работе. Любые идеи?

Ответ 1

Просто используйте @Before (вместо @BeforeClass) (или BeforeTransaction (в зависимости от того, как вы инициализируете базу данных)). Эта аннотация должна быть привязана к нестатическиму общедоступному методу.

Конечно: @Before запускается до КАЖДОГО метода тестового случая (не как @BeforeClass, который запускается только один раз.) Но если вы хотите запустить его ровно один раз, используйте поле статического маркера.

private static boolean initialized = false;
...
@Before
public void initializeDB() { 
   if (!initialized) {
       ... //your db initialization
       initialized = true;
   }
}
---

Ответ 2

Посмотрите на библиотеку DBUnit - она ​​предназначена для выполнения действий, которые вы описываете. Он может создавать и срывать экземпляры базы данных и предоставляет вам простые способы сделать это.

Ответ 3

Попробуйте это решение: fooobar.com/questions/81653/...:

с аннотациями @BeforeAllMethods/@AfterAllMethods вы можете выполнить любой метод в классе Test в контексте экземпляра, где доступны все введенные значения.

Ответ 4

Хотя принятый ответ умный, кажется хакерским. Вы пробовали использовать обычный конструктор?

public class MyJUnitTest {

    public MyJUnitTest() {
       // code for initializeDB
    }

    // Tests

}

Ответ 5

Есть несколько решений этой проблемы:

1- Как упоминалось @Ralph, вы можете использовать аннотацию Junit @Before или @BeforeEach и использовать логическую переменную в качестве флага. Тем не менее, это решение кажется обходным решением! Потому что вы злоупотребляете им, и в некоторых случаях это может сбить с толку.

2- Вместо этого вы можете использовать TestNG, и вам больше не нужно будет использовать статические методы, поэтому вы можете использовать внедренные объекты Spring. Тем не менее, это решение кажется проблематичным! Потребуется время и работа, чтобы перейти с вашей текущей тестовой среды на TestNG.

3- Третьим решением было бы использование Конструктора. Тем не менее, это решение будет проблематичным для инъекции в наследство.

4- Наконец, я бы предложил использовать @PostConstruct, созданный для таких случаев. Смотрите простой пример кода ниже:

@PostConstruct
public void init(){
    initDatabase();
}

Ответ 6

Для JUnit5: Порядок выполнения теста и @TestInstance(Lifecycle.PER_CLASS)

Пример Kotlin:

@ExtendWith(SpringExtension::class)
@TestInstance(PER_CLASS)
class BeforeInstanceTests {

    private var initialized: String = ""
    private val callList: MutableList<String> = ArrayList()

    @BeforeAll
    fun beforeAllNonStatic() {
        initialized = "initialized"
        assertEquals(0, callList.size)
    }

    @Test
    fun test1() {
        assertEquals("initialized", initialized)
        callList.add("test1")
    }

    @Test
    fun test2() {
        assertEquals("initialized", initialized)
        callList.add("test2")
    }

    @Test
    fun test3() {
        assertEquals("initialized", initialized)
        callList.add("test3")
    }

    @AfterAll
    fun afterAllNonStatic() {
        assertEquals("initialized", initialized)
        assertEquals(3, callList.size)
        assertTrue(callList.contains("test1"))
        assertTrue(callList.contains("test2"))
        assertTrue(callList.contains("test3"))

        callList.clear()
        initialized = ""
    }
}