Как выполнить модульное тестирование кода JDBC в Java? - PullRequest
43 голосов
/ 05 ноября 2008

Я хотел бы написать несколько модульных тестов для некоторого кода, который подключается к базе данных, выполняет один или несколько запросов, а затем обрабатывает результаты. (Без фактического использования базы данных)

Другой разработчик здесь написал нашу собственную реализацию DataSource, Connection, Statement, PreparedStatement и ResultSet, которая будет возвращать соответствующие объекты на основе файла конфигурации xml. (мы могли бы использовать фиктивный источник данных и просто запустить тесты с наборами результатов, которые он возвращает).

Мы изобретаем колесо здесь? Что-то подобное уже существует для модульного тестирования? Есть ли другие / лучшие способы тестирования кода JDBC?

Ответы [ 13 ]

30 голосов
/ 22 апреля 2009

У вас есть несколько вариантов:

  • Выполните макет базы данных с помощью библиотеки Mock, например JMock . Огромный недостаток в том, что ваши запросы и данные, скорее всего, вообще не будут проверяться.
  • Используйте легкую базу данных для тестов, такую ​​как HSQLDB . Если ваши запросы просты, это, вероятно, самый простой способ.
  • Выделите базу данных для тестов. DBUnit - хороший вариант, или, если вы используете Maven, вы также можете использовать sql-maven-plugin , чтобы правильно настроить и отключить базу данных (будьте осторожны с зависимостями между тесты). Я рекомендую этот вариант, поскольку он даст вам наибольшую уверенность в том, что запросы правильно работают с вашим поставщиком БД.

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

24 голосов
/ 05 ноября 2008

Вы можете использовать DBUnit вместе с HSQLDB , который может считывать свои исходные данные, например, из файлов CSV.

8 голосов
/ 04 января 2012

Мне нравится использовать комбинацию:

Вы можете продвинуться далеко вперед только с DBUnit и HSQLDB. Unitils предоставляет последнюю милю кода для управления и сброса состояния базы данных. Он также предоставляет удобный способ управления изменениями схемы базы данных и упрощает использование определенных RBDMS (Oracle, DB2, SQL Server и т. Д.). Наконец, Unitils предоставляет несколько приятных оболочек для DBUnit, которые модернизируют API и делают работу с DBUnit намного более приятной.

Если вы еще не проверили Unitils, вам определенно следует это сделать. Унитилс часто упускают из виду и недооценивают.

6 голосов
/ 05 ноября 2008

Используйте любую из фреймворков Mock для такой задачи. ( jMock , и т. Д. .)

Некоторые примеры

4 голосов
/ 05 ноября 2008

Вот почему у вас есть derby (теперь называется JavaDB) или sqlite - это небольшие простые базы данных, которые вы можете создавать, загружать, тестировать и уничтожать относительно быстро и просто. .

2 голосов
/ 01 декабря 2009

Я предпочитаю использовать EasyMock для тестирования кода, который не так просто проверить .

2 голосов
/ 07 ноября 2008

Я бы сказал, что HSQL - это то, что нужно во время ваших юнит-тестов. Цель вашего теста - проверить код jdbc и убедиться, что он работает. Добавление пользовательских классов или насмешка над вызовами jdbc могут легко скрывать ошибки.

Я в основном использую mysql, и когда тесты запускают класс драйвера, а url изменяется на org.hsqldb.jdbcDriver и jdbc: hsqldb: mem: test.

1 голос
/ 03 января 2014

Если вы хотите проводить юнит-тесты, а не интеграционные тесты, чем Вы можете использовать очень простой и простой подход, используя только Mockito, например:

public class JDBCLowLevelTest {

    private TestedClass tested;
    private Connection connection;
    private static Driver driver;

    @BeforeClass
    public static void setUpClass() throws Exception {
        // (Optional) Print DriverManager logs to system out
        DriverManager.setLogWriter(new PrintWriter((System.out)));

        // (Optional) Sometimes you need to get rid of a driver (e.g JDBC-ODBC Bridge)
        Driver configuredDriver = DriverManager.getDriver("jdbc:odbc:url");

        System.out.println("De-registering the configured driver: " + configuredDriver);
        DriverManager.deregisterDriver(configuredDriver);

        // Register the mocked driver
        driver = mock(Driver.class);
        System.out.println("Registering the mock driver: " + driver);
        DriverManager.registerDriver(driver);
    }

    @AfterClass
    public static void tearDown() throws Exception {
        // Let's cleanup the global state
        System.out.println("De-registering the mock driver: " + driver);
        DriverManager.deregisterDriver(driver);
    }

    @Before
    public void setUp() throws Exception {
        // given
        tested = new TestedClass();

        connection = mock(Connection.class);

        given(driver.acceptsURL(anyString())).willReturn(true);
        given(driver.connect(anyString(), Matchers.<Properties>any()))
                .willReturn(connection);

        given(connection.prepareCall(anyString())).willReturn(statement);        
    }
}

Чем вы можете тестировать различные сценарии, как в любом другом тесте Mockito, например,

@Test
public void shouldHandleDoubleException() throws Exception {
    // given
    SomeData someData = new SomeData();

    given(connection.prepareCall(anyString()))
            .willThrow(new SQLException("Prepare call"));
    willThrow(new SQLException("Close exception")).given(connection).close();

    // when
    SomeResponse response = testClass.someMethod(someData);

    // then
    assertThat(response, is(SOME_ERROR));
}
1 голос
/ 08 ноября 2008

Хотя способ макетирования jdbc в вашем приложении, конечно, зависит от того, как вы реализовали свои реальные транзакции jdbc.

Если вы используете jdbc как есть, я бы предположил, что вы написали себе служебный класс для выполнения некоторых задач в строке DBUtils.getMetadataFor(String tablename). Это означает, что вам нужно создать макет этого класса, и это все, что вам нужно. Это было бы довольно простым решением для вас, поскольку у вас, очевидно, уже есть ряд связанных с jdbc фиктивных объектов. Обратите внимание, что я предполагаю, что ваш код jdbc не взорван по всему приложению - если это так, рефакторинг !!!

Однако, если вы используете какой-либо фреймворк для обработки базы данных (например, классы JDBC-шаблонов Spring Framework), вы можете и должны смоделировать класс интерфейса с помощью EasyMock или какого-либо другого аналога. Таким образом, вы можете иметь всю мощь в мире, необходимую для легкого насмешки над соединением.

И последнее, если ничего не работает, вы можете делать то, что уже сказали другие, и использовать DBUnit и / или derby.

1 голос
/ 05 ноября 2008

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

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