JUnit + Derby + printemps: baisse en mémoire db après chaque test
-
12-10-2019 - |
Question
Dans mes tests unitaires, j'autowired quelques sources de données, qui utilisent des URL comme
jdbc:derby:memory:mydb;create=true
pour créer un DB en mémoire.
Pour supprimer un Derby db en mémoire que vous devez vous connecter avec:
jdbc:derby:memory:mydb;drop=true
Je voudrais que cela se produise après chaque test et commencer par un db frais. Comment puis-je faire cela en utilisant Spring?
La solution 2
Comment arrêter Derby base de données en mémoire correctement
m'a donné un indice à une solution:
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
}
}
Un inconvénient est l'utilisation de la chaîne constructeur qui accepte une chaîne (un objet immuable de chaîne autour d'un objet immuable de chaîne). Je lis qu'il ya une annotation @Value au printemps 3, ce qui pourrait aider, mais j'utilise Spring 2.5.
S'il vous plaît laissez-moi savoir si vous avez une solution plus agréable.
Autres conseils
Il y a une façon de faire cette base de données agnostique si vous utilisez Spring avec Hibernate.
Assurez-vous que le contexte d'application sera créé / détruite avant / après chaque méthode d'essai:
@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 {
}
Instruire Hibernate créer automatiquement le schéma au démarrage et d'abandonner le schéma à l'arrêt:
hibernate.hbm2ddl.auto = create-drop
avant chaque test
- le contexte d'application est créée et les grains de ressort requis sont injectés (ressort)
- les structures de base de données sont créés (mise en veille prolongée)
- la import.sql est exécutée si elle est présente (mise en veille prolongée)
et après tous les tests
- le contexte d'application est détruite (ressort)
- le schéma de base de données est supprimée (veille prolongée).
Si vous utilisez les transactions, vous pouvez ajouter le TransactionalTestExecutionListener
.
Après le test du ressort 3, vous pouvez utiliser des annotations pour injecter des configurations:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring-test.xml")
public class MyTest {
}
Il suffit de faire quelque chose comme:
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;
}
}
Faites votre haricots ont une portée de prototype (scope="prototype"
). Cela aura une nouvelle instance de la source de données avant chaque test.
Si vous utilisez la bibliothèque printemps-test.jar , vous pouvez faire quelque chose comme ceci:
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);
}
}
Et une version mise à jour basée sur le dernier commentaire, qui laisse tomber les tables db et reconstitue avant chaque test:
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);
}
}
est ce que nous faisons au début de chaque test.
-
Rejeter tous les Objects précédents.
-
Créer toutes les tables mentionnées dans le create_table.sql
-
Les valeurs insert sur les tables créées à partir de ce que vous voulez tester.
@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"); }
fonctionne comme un charme!