Модульный тест не может удалить базу данных из-за открытого соединения JDBC - PullRequest
0 голосов
/ 12 января 2019

Мы создаем небольшое 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 методы могут вызывать друг друга, что может вызвать осложнения
  • На первый взгляд это кажется плохой практикой

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

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