Мы создаем небольшое Java-приложение, использующее классы модульных тестов, которые нельзя изменить. Приложение использует базу данных SQLite, а один тестовый класс, DAOTest, тестирует класс DAO. При индивидуальном запуске все тесты в DAOTest проходят, однако при выполнении одного за другим только один проходит, остальные не пройдены.
DAO.java:
import java.sql.*;
public class DAO {
private Connection conn = null;
private static final String URL = "jdbc:sqlite:database.db";
public DAO() {
try {
conn = DriverManager.getConnection(URL);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close() {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// methodA(), methodB(), ...
}
DAOTest.java
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import static org.junit.jupiter.api.Assertions.fail;
public class DAOTest {
DAO dao = null;
/**/
@Test
void initDb() {
if (dao != null) {
dao.close();
}
File dbfile = new File("database.db");
ClassLoader classLoader = getClass().getClassLoader();
File srcfile = new File(classLoader.getResource("db/databaseToBeCopied.db").getFile());
Boolean isDbDeleted = false;
try {
isDbDeleted = dbfile.delete();
Files.copy(srcfile.toPath(), dbfile.toPath());
} catch (IOException e) {
e.printStackTrace();
fail("Database deleted: " + isDbDeleted);
}
dao = new DAO();
}
@Test
void testA() {
initDb();
// Call dao.methodA()...
}
@Test
void testB() {
initDb();
// Call dao.methodB()...
}
}
Я понимаю, что является причиной проблемы. initDb()
вызывается в начале каждого теста, чтобы скопировать databaseToBeCopied.db
в database.db
. Функция копирования ожидает, что файл database.db
еще не существует, или выдает FileAlreadyExistsException
. Поскольку переменная dao
в DAOTest.java
является атрибутом non-static
, она равна нулю при каждом вызове initDb()
, поэтому dao.close()
не будет вызываться, и соединение с базой данных не будет закрыто. Теперь это отключает удаление database.db, поэтому функции копирования выдают исключение, и тесты не проходят. Я не могу изменить тестовый класс.
Единственное возможное решение, которое я мог придумать, - это открывать и закрывать соединение с базой данных в каждом отдельном методе DAO.java
, поэтому функция close()
не потребуется. У этого подхода есть пара проблем:
- Я не знаю, насколько эффективно это будет
DAO.java
методы могут вызывать друг друга, что может вызвать осложнения
- На первый взгляд это кажется плохой практикой
Может ли это быть решено другим подходом, возможно, с многопоточностью? Это одна из тем, которые мы вкратце рассмотрели, однако я не очень знаком с ней, поэтому не знаю, как, или вообще можно ли это сделать.