【问题标题】:JMockit Deencapsulation setField not persistingJMockit Deencapsulation setField 不持久
【发布时间】:2017-12-21 19:25:09
【问题描述】:

我正在编写 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 中尝试获取结果列表的行上放置一个断点,我可以从新手表中看到

  1. JMockit 已正确替换查询

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

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

【问题讨论】:

    标签: java jpa derby jmockit


    【解决方案1】:

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

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

    底线,没有办法实现你想要的。相反,要么使用 Oracle 数据库进行集成测试,要么使所有 SQL 代码可移植,避免使用 RDBMS 特定的函数,例如 regexp_like。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多