我正在编写JPA层和数据库之间的集成测试,以检查我写的SQL是否正确。真正的数据库是Oracle,不幸的是,由于我的控制,我的测试数据库必须是Derby,因此自然存在一些差异。例如,我的JPA类具有以下SQL字符串常量
private static final String QUERY = "Select * from Users where regexp_like(user_code, '^SS(B)?N')";
因为Derby不支持regexp_like
我正在使用JMockits Deencapsulation.setField
来动态更改SQL。例如
@Test
public void testMyDaoFind() {
new Expectations() {
{
Deencapsulation.setField(MyClass.class, "QUERY", "Select * from Users");
}
};
dao.findUsers();
}
现在忽略了这不是一个好测试的事实,因为它没有测试将在真实数据库上运行的实际查询(这纯粹是为了满足我对正在发生的事情的好奇心),我得到了一个Eclipselink / Derby抱怨regexp_like的SQL异常错误不会被识别为函数或过程。
如果我在尝试获取结果列表的DAO中的行上放置一个断点,我可以从新手表中看到
JMockit已正确替换查询
getResultList()返回我期待看到的数据
但是,如果我让测试一直运行,那么我得到了前面提到的异常?!
答案 0 :(得分:3)
Java中的字符串不会按照您的思维方式处理。 Java源代码编译器将包含字符串文字的字段中的读取替换为固定的"地址"存储字符串的位置(在类'常量池中);在运行时不再读取该字段。因此,即使JMockit替换了字段中存储的字符串引用,也没有区别,因为使用该字段的客户端代码没有看到该引用。
(顺便说一句,为什么测试将Deencapsulatin.setField
的调用置于期望区块内?这些块仅用于记录预期......)
总而言之,没有办法实现你想要的目标。相反,要么使用Oracle数据库进行集成测试,要么使所有SQL代码都可移植,避免使用特定于RDBMS的函数,例如regexp_like
。