Есть ли где-нибудь набор заглушек / макетов для JDBC? - PullRequest
7 голосов
/ 20 июля 2009

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

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

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

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

Ответы [ 6 ]

7 голосов
/ 20 июля 2009

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

4 голосов
/ 20 июля 2009

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

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

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

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

2 голосов
/ 02 августа 2013

jOOQ поставляется с MockConnection, который может быть снабжен MockDataProvider, что намного проще в реализации, чем полный JDBC API. Этот пост в блоге показывает, как использовать 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
2 голосов
/ 20 июля 2009

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

1 голос
/ 20 июля 2009

Хотя я большой поклонник модульного тестирования в целом, я считаю, что он имеет ограниченную ценность для DAO.

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

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

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

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

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

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

0 голосов
/ 31 декабря 2013

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

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

Раскрытие: это мои рамки.

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