Is there a way to test that default TimeZone is never used in a JUnit Test using EasyMock/PowerMock?

huangapple go评论155阅读模式
英文:

Is there a way to test that default TimeZone is never used in a JUnit Test using EasyMock/PowerMock?

问题

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

有办法实现这一点吗?


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

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

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

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

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

英文:

I'd like to prove that a piece of code that I've written is not affected by the default Timezone (set either as a JVM property or through the setDefault() method) as part of a unit test.

Is there a way to accomplish this?


The reason that this isn't as simple as setting default Timezone within the test before calling the method is that I'm trying to test safety against a race condition. For example, consider the following:

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

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

This test should pass, but what happens if the default timezone suddenly changes between the two getInstance() calls, from GMT to Singapore, because another piece of code running somewhere changes the default timezone? Then we have a situation where it might fail.

The only way that I can think of to show that it will be unaffected for all possible changes is to somehow assert that the code does not access the default timezone value, wherever it is.

答案1

得分: 0

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

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() 之间更改了属性,那么这将无关紧要。

英文:

In this case, I would provoke the race condition. You add an artificial method to your code and use a partial mock or an manual mock to change the timezone.

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

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

If the idea is just to know if a setDefault is called somewhere during your code execution, you can use PowerMock to mock setDefault and fail if it is called. However, I'm not sure PowerMock can mock java.* classes. You might need a ByteBuddy agent.

There is one pitfall left. The default locale can be set using system properties. However, if the property is changed between the two getInstance(), it won't matter.

huangapple
  • 本文由 发表于 2020年8月5日 03:23:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63253782.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定