Есть ли набор заглушек / насмешек для JDBC, доступных в любом месте?

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

автор принятого ответа предполагает, что может быть полезно издеваться над всем уровнем базы данных для проверки сгенерированного SQL. Я не придал этому большого значения, когда впервые прочитал ответ несколько месяцев назад, но недавно я заметил несколько ошибок, вызванных неправильно сгенерированным SQL, неправильно назначенными полями и так далее. Я понимаю, что JDBC довольно раздут и подвержен ошибкам, но на данный момент это не вариант переключиться на что-то другое.

рассматриваемое приложение является пакетным процессором каналов данных и использует JDBC напрямую, а не ORM. Весь код JDBC разделен на отдельные объекты DAO, где каждый объект имеет свой собственный интерфейс и stub, помимо фактических реализаций. Это позволило мне достичь хорошего тестового покрытия бизнес-уровня, но тестирование уровня базы данных практически не существует.

существует ли существующая реализация заглушки JDBC (java.sql) интерфейсы, которые можно ввести в классы DAO и использовать для проверки сгенерированного SQL и, возможно, отправить обратно некоторые запрограммированные результаты?

6 ответов


Я не знаю, видели вы это или нет, но есть MockRunner. Он предоставляет множество классов, реализующих интерфейсы JDBC (а также других J2EEclasses). Вот!--3-->макет объектов JDBC. Есть также довольно много примеры.


похоже, у вас проблемы с самим кодом DAO? В противном случае слой DAO является очевидным местом для вашего насмешки, но если вы пытаетесь проверить DAO, вам нужно будет высмеять то, что находится ниже.

лично я, как правило, держусь подальше от насмешек над большими, сложными библиотеками; если вам действительно нужно проверить слой DAO напрямую, и DAO работает непосредственно с JDBC, у вас есть три очевидных варианта:

  1. запустите интегрированный тест, который включает DAO и JDBC вместе с базой данных
  2. добавить слой выше JDBC с более тонким интерфейсом, лучше подходит для насмешек.
  3. использование JDBC издевается либо над вашим собственным письмом, либо над некоторыми из перечисленных выше элементов.

Я почти всегда выбирал #1 или #2. Потому что есть множество возможностей ошибок в неправильном синтаксисе SQL и тому подобное, я склоняюсь к #1. Однако я понимаю, что вы просите не об этом. ;)


вы можете проверить базу данных напрямую с помощью д. Банкрофт.


jOOQ суда MockConnection это можно обеспечить с MockDataProvider, что намного проще реализовать, чем полный API JDBC. Это сообщение в блоге показывает, как использовать MockConnection: http://blog.jooq.org/2013/02/20/easy-mocking-of-your-database/

пример:

MockDataProvider provider = new MockDataProvider() {

    // Your contract is to return execution results, given a context
    // object, which contains SQL statement(s), bind values, and some
    // other context values
    @Override
    public MockResult[] execute(MockExecuteContext context) 
    throws SQLException {

        // Use ordinary jOOQ API to create an org.jooq.Result object.
        // You can also use ordinary jOOQ API to load CSV files or
        // other formats, here!
        DSLContext create = DSL.using(...);
        Result<MyTableRecord> result = create.newResult(MY_TABLE);
        result.add(create.newRecord(MY_TABLE));

        // Now, return 1-many results, depending on whether this is
        // a batch/multi-result context
        return new MockResult[] {
            new MockResult(1, result)
        };
    }
};

// Put your provider into a MockConnection and use that connection
// in your application. In this case, with a jOOQ DSLContext:
Connection connection = new MockConnection(provider);
DSLContext create = DSL.using(connection, dialect);

// Done! just use regular jOOQ API. It will return the values
// that you've specified in your MockDataProvider
assertEquals(1, create.selectOne().fetch().size());

есть еще MockFileDatabase, который поможет вам сопоставить фиктивные результаты со строками SQL, написав текст файл такой:

# This is a sample test database for MockFileDatabase
# Its syntax is inspired from H2's test script files

# When this query is executed...
select 'A' from dual;
# ... then, return the following result
> A
> -
> A
@ rows: 1

# Just list all possible query / result combinations
select 'A', 'B' from dual;
> A B
> - -
> A B
@ rows: 1

select "TABLE1"."ID1", "TABLE1"."NAME1" from "TABLE1";
> ID1 NAME1
> --- -----
> 1   X
> 2   Y
@ rows: 2

хотя я большой поклонник модульного тестирования в целом, я обнаружил, что он имеет ограниченное значение с DAOs.

то, что я видел, - это то, что вполне возможно написать тесты (используя любой из насмешливых API - JMock, EasyMock и т. д.), Они обычно работают сразу (логика настолько проста, как они не могли), только ломаются, когда вы меняете код (добавляя значение, например), и это просто делает их бременем на базе кода.

I думаю, это потому, что мои DAOs обычно следуют форме:

  • сделать подключение.
  • create оператор.
  • установленных значений.
  • чтение значений (для операций загрузки).
  • очистить.

затем вы делаете предположения о том, как драйвер JDBC будет/работает(ing), и вы получаете тест, который на самом деле ничего не делает, кроме тестирования некоторого простого кода, вызывается в том порядке, в котором он объявлен.

ошибки исходящие из DAOs обычно происходят в базе данных (ключевые нарушения, ошибки в хранимых процедурах и т. д.), И если вы не используете систему в целом, вы не увидите этих ошибок.

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


Если вы хотите проверить уровень персистентности (ORM, DAO,...) действует, как ожидалось, в соответствии с различными случаями JDBC (например, когда он получает такое количество результирующего набора/обновления, тогда он должен делать это и то), тогда Acolyte framework должен быть рассмотрен.

Это позволяет создавать соединение JDBC, которым вы управляете через обработчик, поэтому вы выбираете, что возвращается для каждого запроса/ обновления:https://github.com/cchantep/acolyte