我想为一些连接到数据库的代码编写一些单元测试,运行一个或多个查询,然后处理结果。 (没有实际使用数据库)
这里的另一个开发人员编写了我们自己的DataSource,Connection,Statement,PreparedStatement和ResultSet实现,它们将根据xml配置文件返回相应的对象。 (我们可以使用伪数据源,只针对它返回的结果集运行测试)。
我们在这里重新发明轮子吗?这样的单元测试是否已经存在? 是否有其他/更好的方法来测试jdbc代码?
答案 0 :(得分:30)
您有几种选择:
有时,使这些测试可配置是必要且有用的,这样只有在数据库可用时才执行这些测试。这可以用例如建立属性。
答案 1 :(得分:24)
答案 2 :(得分:8)
我喜欢使用以下组合:
您只需使用DBUnit和HSQLDB即可。 Unitils提供管理和重置数据库状态的最后一英里代码。它还提供了一种管理数据库模式更改的好方法,并且可以轻松使用特定的RBDMS(Oracle,DB2,SQL Server等)。最后,Unitils围绕DBUnit提供了一些不错的包装器,它使API现代化并使DBUnit更加愉快。
如果你尚未检查出Unitils,你肯定应该。 Unitils经常被忽视并且不被重视。
答案 3 :(得分:6)
答案 4 :(得分:4)
答案 5 :(得分:2)
我想说HSQL是你进行单元测试的方法。测试的重点是测试你的jdbc代码并确保它的工作原理。添加自定义类或模拟jdbc调用可以轻松隐藏错误。
我主要使用mysql,当测试运行驱动程序类时,url更改为org.hsqldb.jdbcDriver和jdbc:hsqldb:mem:test。
答案 6 :(得分:2)
我更喜欢使用EasyMock来测试不那么容易测试的代码。
答案 7 :(得分:1)
有DBUnit。它不允许您在没有数据库的情况下测试您的jdbc代码,但似乎您可以通过模拟数据库来引入一组不同的购买。
答案 8 :(得分:1)
虽然在应用程序中模拟jdbc的方法当然取决于你如何实现你的实际jdbc事务。
如果您按原样使用jdbc,我假设您已经编写了一个实用类,可以在DBUtils.getMetadataFor(String tablename)
行中执行某些任务。这意味着你必须创建一个类的模拟,这可能就是你所需要的。这对您来说是相当简单的解决方案,因为您显然已经有一系列与jdbc相关的模拟对象可用。请注意,我假设你的jdbc代码没有在应用程序周围爆炸 - 如果是,重构!!!
如果您正在使用任何框架进行数据库处理(如Spring Framework的JDBC模板类),您可以并且应该使用EasyMock或其他等效方法来模拟接口类。通过这种方式,您可以拥有世界上所需的所有功能,以便轻松模拟连接。
最后如果没有其他工作,你可以做其他人已经说过的事情并使用DBUnit和/或德比。
答案 9 :(得分:1)
如果你想进行单元测试,而不是集成测试 您可以使用一种非常基本且简单的方法,仅使用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));
}
答案 10 :(得分:0)
我们使用Mockrunner。 http://mockrunner.sourceforge.net/它内置了模拟连接和数据源,因此无需自己实现它们。
答案 11 :(得分:0)
Acolyte驱动程序可用于模拟JDBC连接,在测试期间管理它并将数据作为结果集返回(使用其类型安全的行列表API):https://github.com/cchantep/acolyte
注意:我是Acolyte的作者。
答案 12 :(得分:0)