如何在java中对jdbc代码进行单元测试?

问题描述 投票:43回答:13

我想为一些连接到数据库的代码编写一些单元测试,运行一个或多个查询,然后处理结果。 (没有实际使用数据库)

这里的另一个开发人员编写了我们自己的DataSource,Connection,Statement,PreparedStatement和ResultSet实现,它们将根据xml配置文件返回相应的对象。 (我们可以使用伪数据源,只针对它返回的结果集运行测试)。

我们在这里重新发明轮子吗?这样的单元测试是否已经存在?是否有其他/更好的方法来测试jdbc代码?

java database unit-testing jdbc junit
13个回答
24
投票

您可以将DBUnitHSQLDB一起使用,JMock可以从CSV文件中读取其初始数据。


1
投票

如果你想进行单元测试,而不是集成测试,那么你可以使用一个非常基本和简单的方法,只使用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));
}

比你可以测试各种场景,比如任何其他Mockito测试,例如

http://mockrunner.sourceforge.net/

0
投票

我们使用Mockrunner。 https://github.com/cchantep/acolyte它内置了模拟连接和数据源,因此无需自己实现它们。


0
投票

Acolyte驱动程序可用于模拟JDBC连接,在测试期间管理它并将数据作为结果集返回(使用其类型安全行列表API):http://jdbdt.org

注意:我是Acolyte的作者。


0
投票

看看JDBDT:qazxswpoi

您可以将它用于数据库设置和断言,作为DBUnit的替代方案。

注意:我是JDBDT的作者。


30
投票

你有几个选择:

  • 使用Mock库模拟数据库,例如HSQLDB。这样做的巨大缺点是您的查询和数据很可能根本不会被测试。
  • 使用轻量级数据库进行测试,例如DBUnit。如果您的查询很简单,这可能是最简单的方法。
  • 为测试专用数据库。 sql-maven-plugin是一个不错的选择,或者如果你使用Maven,你也可以使用DBUnit正确设置和拆除数据库(注意测试之间的依赖关系)。我建议使用此选项,因为它将使您最有信心查询与数据库供应商正常工作。

有时,使这些测试可配置是必要且有用的,这样只有在数据库可用时才执行这些测试。这可以用例如建立属性。


8
投票

我喜欢使用以下组合:

只需DBUnit和HSQLDB就可以获得相当远的成就。 Unitils提供管理和重置数据库状态的最后一英里代码。它还提供了一种管理数据库模式更改的好方法,并且可以轻松使用特定的RBDMS(Oracle,DB2,SQL Server等)。最后,Unitils围绕DBUnit提供了一些不错的包装器,它使API现代化并使DBUnit更加愉快。

如果你尚未检查出Unitils,你肯定应该。 Unitils经常被忽视和低估。


6
投票

使用任何Mock框架来完成这样的任务。 (etcexamples。)

一些derby


4
投票

这就是为什么你有sqlite(现在称为JavaDB)或EasyMock - 它们是小型,简单的数据库,你可以相对快速和简单地创建,加载,测试和销毁。


2
投票

我会说HSQL是您进行单元测试时的方法。测试的重点是测试你的jdbc代码并确保它的工作原理。添加自定义类或模拟jdbc调用可以轻松隐藏错误。

我主要使用mysql,当测试运行驱动程序类时,url更改为org.hsqldb.jdbcDriver和jdbc:hsqldb:mem:test。


2
投票

我更喜欢使用DBUnit来测试一个不那么容易测试的代码。


1
投票

DBUtils.getMetadataFor(String tablename)。它不允许您在没有数据库的情况下测试您的jdbc代码,但似乎您可以通过模拟数据库来引入一组不同的购买。


1
投票

虽然在应用程序中模拟jdbc的方法当然取决于你如何实现实际的jdbc事务。

如果您按原样使用jdbc,我假设您已经编写了一个实用类,可以在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); } } 中执行某些任务。这意味着你必须创建一个类的模拟,这可能就是你所需要的。这对您来说是相当简单的解决方案,因为您显然已经有一系列与jdbc相关的模拟对象可用。请注意,我假设你的jdbc代码没有在应用程序周围爆炸 - 如果是,重构!!!

但是,如果您使用任何框架进行数据库处理(如Spring Framework的JDBC模板类),您可以并且应该使用EasyMock或其他等效方法来模拟接口类。这样,您可以拥有世界上所需的所有功能,以便轻松模拟连接。

最后如果没有其他工作,你可以做别人已经说过的事情,并使用DBUnit和/或德比。

© www.soinside.com 2019 - 2024. All rights reserved.