JUnit + Derby + Spring: падение в памяти db после каждого теста

в моих модульных тестах я autowired некоторые источники данных, которые используют URL-адреса, такие как

jdbc:derby:memory:mydb;create=true

для создания DBs в памяти.

чтобы удалить в памяти Derby db, вы должны связаться с:

jdbc:derby:memory:mydb;drop=true

Я хотел бы, чтобы это происходило после каждого теста и начиналось со свежей БД. Как я могу сделать это с помощью Spring?

6 ответов


существует агностический способ сделать это, если вы используете Spring вместе с Hibernate.

убедитесь, что контекст приложения будет создан / уничтожен до / после каждого метода тестирования:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:application-context-test.xml"})
@TestExecutionListeners({DirtiesContextTestExecutionListener.class, 
    DependencyInjectionTestExecutionListener.class})
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public abstract class AbstractTest {

}

проинструктировать Hibernate автоматически создавать схему при запуске и удалять схему при завершении работы:

hibernate.hbm2ddl.auto = create-drop

Теперь перед каждым тестом

  • создается контекст приложения и вводятся необходимые весенние бобы (весна)
  • создаются структуры базы данных (hibernate)
  • импорт.sql выполняется, если присутствует (hibernate)

и после каждого испытания

  • контекст приложения уничтожается (весна)
  • схема базы данных удалена (спящий режим).

Если вы используете транзакции, вы можете добавить TransactionalTestExecutionListener.


Как правильно отключить базу данных Derby в памяти

дал мне подсказку к решению:

    mydb.drop.url = jdbc:derby:memory:mydb;drop=true

    ...

    <bean id="mydbDropUrl" class="java.lang.String">
    <constructor-arg value="${mydb.drop.url}" />
</bean>

    ...

    @Resource
private String mydbDropUrl;        

    @After
public void tearDown() {
    try {
        DriverManager.getConnection(mydbDropUrl);
    } catch (SQLException e) {
        // ignore
    }
}

недостатком является использование строкового конструктора, который принимает строку (неизменяемый строковый объект вокруг неизменяемого строкового объекта). Я читал, что в Spring 3 есть аннотация @Value, которая может помочь здесь, но я использую Spring 2.5.

пожалуйста, дайте мне знать, если у вас есть лучше решение.


после весеннего теста 3 Вы можете использовать аннотации для ввода конфигураций:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-test.xml")
public class MyTest {
}

просто сделайте что-то вроде:

public class DatabaseTest implements ApplicationContextAware {
    private ApplicationContext context;
    private DataSource source;

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.context = applicationContext;
    }

    @Before
    public void before() {
        source = (DataSource) dataSource.getBean("dataSource", DataSource.class);
    }

    @After
    public void after() {
        source = null;
    }
}

Сделайте ваш bean иметь область прототипа (scope="prototype"). Это позволит получить новый экземпляр источника данных перед каждым тестом.


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

public class MyDataSourceSpringTest extends
AbstractTransactionalDataSourceSpringContextTests {

    @Override
    protected String[] getConfigLocations() {
        return new String[]{"classpath:test-context.xml"};
    }

    @Override
    protected void onSetUpInTransaction() throws Exception {
        super.deleteFromTables(new String[]{"myTable"});
        super.executeSqlScript("file:db/load_data.sql", true);
    }
}

и обновленная версия на основе последнего комментария, которая отбрасывает БД и воссоздает таблицы перед каждым тестом:

public class MyDataSourceSpringTest extends
    AbstractTransactionalDataSourceSpringContextTests {

        @Override
        protected String[] getConfigLocations() {
            return new String[]{"classpath:test-context.xml"};
        }

        @Override
        protected void onSetUpInTransaction() throws Exception {
            super.executeSqlScript("file:db/recreate_tables.sql", true);
        }
}

Это то, что мы делаем в начале каждого теста.

  1. удалить все предыдущие объекты.

  2. создайте все таблицы, упомянутые в create_table.в SQL

  3. вставить значения на созданные таблицы на основе того, что вы хотите проверить.

      @Before
      public void initialInMemoryDatabase() throws IOException, FileNotFoundException {
    
      inMemoryDerbyDatabase.dropAllObjects();
      inMemoryDerbyDatabase.executeSqlFile("/create_table_policy_version_manager.sql");
      inMemoryDerbyDatabase.executeSqlFile("/insert_table_policy_version_manager.sql");
    
      }
    

работает как шарм!