java - JMockit Deencapsulation setField 不持久

标签 java jpa derby jmockit

我正在我的 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 的 SQL 异常错误提示 regexp_like 未被识别为函数或过程。

如果我在 DAO 中尝试获取结果列表的行上放置一个断点,我可以从一个新 watch 中看到

  1. JMockit 已正确替换查询

  2. getResultList() 返回我期望看到的数据

但是,如果我让测试一直运行,那么我会得到上述异常?!

最佳答案

Java 中的字符串处理方式与您想象的不同。 Java 源代码编译器用存储字符串的固定“地址”(在类的常量池中)替换从保存字符串文字的字段读取;该字段在运行时不再读取。因此,即使 JMockit 替换了字段中存储的字符串引用,也没有任何区别,因为使用该字段的客户端代码看不到该引用。

(顺便说一句,为什么测试将对 Deencapsulatin.setField 的调用放在期望 block 中?这样的 block 仅用于记录期望...)

归根结底,您无法实现您的目标。相反,要么使用 Oracle 数据库进行集成测试,要么使所有 SQL 代码可移植,避免 RDBMS 特定的函数,例如 regexp_like

关于java - JMockit Deencapsulation setField 不持久,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45141157/

相关文章:

java - Hibernate对于Web应用程序更安全吗?

Java Servlet 大量请求和线程

java - Google glass 返回 glass.widget.CardBuilder 的 NoClassDefFoundError

java - Spring Rest Api Json 响应不显示属性名称

java - Derby 数据库的 SQL 语句错误

java - 如何连接 Apache Derby 数据库中的三个表?

java - 将 fragment 作为参数传递给 RecyclerView.Adapter 是一种不好的做法吗?帮助点击

hibernate - Spring Roo @Transient 不工作

java - "spring.data.web.pageable.one-indexed-parameters=true"不起作用

java - 如何更正 java.sql.SQLException : Database 'dbname' not found error?