【问题标题】:Is there a way to test that default TimeZone is never used in a JUnit Test using EasyMock/PowerMock?有没有办法使用 EasyMock/PowerMock 来测试 JUnit 测试中从不使用默认时区?
【发布时间】:2020-08-07 01:28:42
【问题描述】:

我想证明,作为单元测试的一部分,我编写的一段代码不受默认时区(设置为 JVM 属性或通过 setDefault() 方法)的影响。

有没有办法做到这一点?


这不像在调用方法之前在测试中设置默认时区那么简单,因为我正在尝试针对竞争条件测试安全性。例如,考虑以下情况:

Calendar calendar = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();

assertEquals(calendar.get(Calendar.DATE), calendar2.get(Calendar.DATE));

这个测试应该可以通过,但是如果默认时区在从 GMT 到新加坡的两个 getInstance() 调用之间突然发生变化,因为在某处运行的另一段代码更改了默认时区,会发生什么?那么我们就有可能失败的情况。

我能想到的唯一表明它不会对所有可能的更改产生影响的方法是,以某种方式断言代码不会访问默认时区值,无论它在哪里。

【问题讨论】:

  • 也许是一个参数化测试,它需要不同的时区来调用 TimeZone.setDefault(...),并为所有情况断言相同的结果。显示一些代码会有所帮助。
  • 您好安德鲁,感谢您的评论。我编辑了问题以使其更清晰,并添加了一个基本代码 sn-p 可以更好地说明问题。
  • 仍然不确定:您要确保没有代码更改默认时区,还是要确保您的代码不关心默认时区是什么?
  • 第一种可以用Checkstyle之类的工具检查,也可以直接搜索源码;但后者可能是更安全的方法。 Andrew 已经建议如何做到这一点,如果您想到竞争条件(为什么会发生这种情况?),您可以在测试中运行多个线程,但这会变得混乱 :-(
  • 感谢您的评论。我想确保我自己的代码不关心默认时区是什么。我知道正在运行的其他代码确实会更改默认时区,因此这是我的代码与其他一些我无法更改的代码之间的竞争条件。我需要单元测试的原因是我试图证明代码更改会导致修复,所以基本上单元测试在更改之前失败,但在修复之后通过。

标签: java junit4 powermock easymock


【解决方案1】:

在这种情况下,我会引发竞争条件。您在代码中添加人工方法,并使用部分模拟或手动模拟来更改时区。

Calendar calendar = Calendar.getInstance();
changeTimeZone();
Calendar calendar2 = Calendar.getInstance();

assertEquals(calendar.get(Calendar.DATE), calendar2.get(Calendar.DATE));

如果只是想知道在代码执行期间是否在某处调用了 setDefault,则可以使用 PowerMock 模拟 setDefault,如果被调用则失败。但是,我不确定 PowerMock 是否可以模拟 java.* 类。您可能需要一个 ByteBuddy 代理。

还有一个陷阱。可以使用系统属性设置默认语言环境。但是,如果属性在两个getInstance() 之间发生变化,则无关紧要。

【讨论】:

  • 嗨,亨利,感谢您的评论。所以这种方法在某种意义上是有效的,它可以表明存在问题,如果我已经确定了问题,但它不像我希望的那样具有可扩展性。限制是您必须将 changeTimeZone() 方法放在要测试的每一行代码之间,即使那样,也不能保证您会抓住它(如果我们正在检查日期的相等性,则日期本身可能会或可能不会翻转)。
  • 您知道是否有办法在 TimeZone.getDefault() 方法上放置某种侦听器作为测试的一部分,以便在调用该方法时测试失败?因此,如果调用了例如 Calendar.getInstance(),这将失败,因为 getInstance() 调用 getDefault()。我对其他解决方案完全开放,但我正在寻找一个非常通用/严格的解决方案,例如,我可以将它作为注释/方法添加到许多测试中,以表明该方法永远不会被调用。
  • 但是,在您的实际应用程序中,如果任何线程可以更改时区,它不会解决您的问题。如果一切都发生在同一个线程中并且您只是不知道调用了什么代码,那么可以。我会更新答案。
  • 我认为 Powermock 是正确的解决方案,所以我会接受你的回答。由于各种原因,Powermock 似乎与我的其他测试实用程序发生冲突,因此我无法将其用于我的目的,但我认为对于其他有此问题的人来说,这是一种可行的方法。
  • 尝试升级测试依赖以获得正确的依赖组合
猜你喜欢
  • 2017-02-07
  • 1970-01-01
  • 2011-04-12
  • 1970-01-01
  • 2020-04-28
  • 1970-01-01
  • 2022-07-05
  • 1970-01-01
  • 2023-03-12
相关资源
最近更新 更多