Макетный драйвер базы данных
Есть ли какой-нибудь драйвер JDBC, который просто игнорирует вызовы базы данных?
Для разработки я перенесу приложение на виртуальную машину. Здесь я хочу работать только над частью GUI. Но приложение делает несколько запросов к базе данных, которая не позволяет приложению даже запуститься. Я не хочу менять код приложения в настоящее время, так как база данных в значительной степени связана.
Поэтому я подумал, что может быть драйвер JDBC, который просто возвращает пустые результаты для запросов.
7 ответов
Я решил написать собственный простой макет драйвера. Это было довольно просто и сделало то, что я хочу. Я могу переключить драйвер базы данных приложения с помощью файла конфигурации, чтобы позволить приложению использовать мой драйвер простым способом.
Затем я расширил драйвер, чтобы он возвращал данные, которые он анализирует из файлов CSV. Я опубликовал код в коде Google, может быть, кто-то еще может использовать его: dummyjdbc
Есть некоторые "пустые" драйверы JDBC как часть Mocking framewroks, например MockDriver от Mockrunner.
Но использование этого требует некоторого кодирования.
Это потому, что когда приложение Java подключается к базе данных, оно предоставляет URL-адрес JDBC в форме jdbc:mysql://localhost
, Система ищет, какой драйвер зарегистрирован в нем для обработки URL-адресов такого типа, и выбирает подходящий драйвер. Информация о том, какие драйверы типов URL-адресов поддерживаются, содержится в самом драйвере, и фиктивный драйвер не может содержать в себе все известные типы URL-адресов - здесь нет такой вещи, как подстановочные знаки, и любой список не будет полным.
Итак, если вы можете вызвать JDBCMockObjectFactory.registerMockDriver() в приложении до того, как оно подключится к базе данных - оно выполнит эту работу. Если нет - я не думаю, что это возможно. Тем не менее, небольшая модификация кода драйвера сделает это... но опять же - требуется кодирование.
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
Моя платформа Acolyte - это протестированный драйвер JDBC, разработанный для таких целей (макет, тестирование,...): https://github.com/cchantep/acolyte
Он уже использовался в нескольких проектах с открытым исходным кодом, либо в vanilla Java, либо с использованием Scala DSL:
// Register prepared handler with expected ID 'my-unique-id'
acolyte.Driver.register("my-unique-id", handler);
// then ...
Connection con = DriverManager.getConnection(jdbcUrl);
// ... Connection |con| is managed through |handler|
Если вы хотите выполнять модульные тесты, а не интеграционные тесты, вы можете использовать очень простой и простой подход, используя только 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);
}
}
Чем вы можете протестировать различные сценарии, как в любом другом тесте 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));
}
Никогда не слышал о таком водителе сам. Если вы не найдете ни одного, вы можете использовать базу данных, такую как HSQLDB. Вы можете настроить его для использования таблиц в памяти, чтобы больше ничего не записывалось на диск. Однако вам придется использовать другую строку подключения.
Если вы используете Spring, создайте свой собственный класс, который реализует Datasource и у которого методы ничего не делают.