如何模拟DB进行测试(Java)?
我用Java编程,我的应用程序大量使用DB。因此,能够轻松测试我的数据库使用情况对我来说很重要。如何模拟DB进行测试(Java)?,java,database,unit-testing,testing,jdbc,Java,Database,Unit Testing,Testing,Jdbc,我用Java编程,我的应用程序大量使用DB。因此,能够轻松测试我的数据库使用情况对我来说很重要。 DB测试都是关于什么的?对我来说,他们应该提供两个简单的要求: 验证SQL语法 更重要的是,检查数据是否根据给定情况正确选择/更新/插入 那么,看来我只需要一个DB。 但实际上,我不希望这样,因为使用DB进行测试没有什么困难: “给自己准备一个测试数据库,有多难?”-好吧,在我的工作场所,拥有一个个人测试数据库是不可能的。您必须使用“公共”数据库,每个人都可以访问它 “这些测试肯定不是很快……”D
DB测试都是关于什么的?对我来说,他们应该提供两个简单的要求:
但实际上,我不希望这样,因为使用DB进行测试没有什么困难:
- “给自己准备一个测试数据库,有多难?”-好吧,在我的工作场所,拥有一个个人测试数据库是不可能的。您必须使用“公共”数据库,每个人都可以访问它
- “这些测试肯定不是很快……”DB测试往往比普通测试慢。进行缓慢的测试确实不理想
- “这个程序应该可以处理任何情况!”-它变得有些烦人,甚至不可能在DB中尝试和模拟每个情况。对于每种情况,都应该进行一定量的插入/更新查询,这很烦人,而且需要时间
- “等一下,你怎么知道这个表中有542行?”-测试的主要原则之一,是能够以不同于测试代码的方式测试功能。当使用DB时,通常有一种方法来做某事,因此测试与核心代码完全相同
编辑:谢谢您的回答!虽然我想要一个工具,但你也给了我一些关于这个问题的提示:)我需要一些时间来查看你的报价,所以我现在不能说你的答案是否令人满意 无论如何,这里有一个更好的视图来说明我要查找的内容—假设一个名为DBMonitor的类,它的一个特性是查找表中的行数。下面是我想如何使用JUnit测试该功能的虚构代码:
public class TestDBMonitor extends TestCase {
@Override
public void setUp() throws Exception {
MockConnection connection = new MockConnection();
this.tableName = "table1";
MockTable table = new MockTable(tableName);
String columnName = "column1";
ColumnType columnType = ColumnType.NUMBER;
int columnSize = 50;
MockColumn column = new MockColumn(columnName, columnType, columnSize);
table.addColumn(column);
for (int i = 0; i < 20; i++) {
HashMap<MockColumn, Object> fields = new HashMap<MockColumn, Object>();
fields.put(column, i);
table.addRow(fields);
}
this.connection = connection;
}
@Test
public void testGatherStatistics() throws Exception {
DBMonitor monitor = new DBMonitor(connection);
monitor.gatherStatistics();
assertEquals(((MockConnection) connection).getNumberOfRows(tableName),
monitor.getNumberOfRows(tableName));
}
String tableName;
Connection connection;
}
公共类TestDBMonitor扩展了TestCase{
@凌驾
public void setUp()引发异常{
MockConnection连接=新的MockConnection();
this.tableName=“table1”;
模拟表格=新模拟表格(表格名称);
字符串columnName=“column1”;
ColumnType ColumnType=ColumnType.NUMBER;
int columnSize=50;
MockColumn column=新的MockColumn(columnName、columnType、columnSize);
表.添加列(列);
对于(int i=0;i<20;i++){
HashMap字段=新的HashMap();
字段。put(第i列);
表.addRow(字段);
}
这个连接=连接;
}
@试验
public void testGatherStatistics()引发异常{
DBMonitor monitor=新的DBMonitor(连接);
monitor.gatherStatistics();
assertEquals(((MockConnection)connection).getNumberOfRows(tableName),
monitor.getNumberOfRows(tableName));
}
字符串表名;
连接;
}
我希望这段代码足够清晰,能够理解我的想法(请原谅语法错误,我是在没有我亲爱的Eclipse:p的情况下手动键入的)
顺便说一句,我部分使用了ORM,我的原始SQL查询非常简单,不同平台之间不应该有所不同 我已经用过了。基本上,它是一个JAR文件(一个纯Java内存数据库),您可以在它自己的JVM或您自己的JVM中运行,当它运行时,您有一个数据库。然后停止它,数据库就会消失。到目前为止,我把它作为一个纯内存数据库使用。运行单元测试时,通过Ant启动和停止非常简单。Java随附
也就是说,我建议不要使用与生产中使用的不同类型的DB,除非您使用ORM层。否则,您的SQL可能不会像您想象的那样跨平台
另外,首先,您是否使用ORM层访问数据库?
如果不是:那么你所想的就没有用了。当你不确定你正在激发的SQL是否能在生产中与你的DB一起工作时,测试有什么用,就像在测试用例中你正在使用其他东西一样。
如果是:那么您可以查看指出的各种选项。我们正在创建一个数据库测试环境。我们觉得我们必须使用一个带有模拟数据的真实数据库管理系统。模拟DBMS的一个问题是SQL从来没有真正完全固定为标准,因此人工测试环境必须忠实地支持生产数据库的方言。另一个问题是,我们广泛使用列值约束、外键约束和唯一约束,由于人工工具可能无法实现这些约束,我们的单元测试可能会通过,但当系统测试第一次遇到真正的约束时就会失败。如果测试花费的时间太长,这表明存在实现错误,我们将调整查询(通常测试数据集与生产数据集相比非常小) 我们已经在每台开发人员机器以及持续集成和测试服务器(我们使用Hudson)上安装了一个真正的DBMS。我不知道您的工作策略限制是什么,但是安装和使用PostgreSQL、MySQL和Oracle X非常容易
import static java.lang.System.out;
import java.sql.*;
import org.jooq.tools.jdbc.*;
public class Mocking {
public static void main(String[] args) throws Exception {
MockDataProvider db = new MockFileDatabase(
Mocking.class.getResourceAsStream("/mocking.txt");
try (Connection c = new MockConnection(db));
Statement s = c.createStatement()) {
out.println("Actors:");
out.println("-------");
try (ResultSet rs = s.executeQuery(
"select first_name, last_name from actor")) {
while (rs.next())
out.println(rs.getString(1)
+ " " + rs.getString(2));
}
}
}
}