如何编写单元测试,以确保我的基于日期/时间的代码在所有时区均可使用,而无论是否启用DST? [英] How do I write unit tests to make sure my date/time based code works for all time zones and with/out DST?

查看:142
本文介绍了如何编写单元测试,以确保我的基于日期/时间的代码在所有时区均可使用,而无论是否启用DST?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用JodaTime 2.1,我正在寻找一种单元测试代码的模式,该模式执行日期/时间操作以确保其在所有时区均正常运行,并且独立于 DST

I'm using JodaTime 2.1 and I'm looking for a pattern to unit test code which performs date/time operations to make sure it behaves well for all time zones and independent of DST.

具体是:


  1. 如何模拟系统时钟(因此,我不必模拟所有调用 new DateTime()的地方获取当前时间)

  2. 如何为默认时区做同样的事情?

  1. How can I mock the system clock (so I don't have to mock all the places where I call new DateTime() to get the current time)
  2. How can I do the same for the default time zone?


推荐答案

您可以为此使用 @Rule 。以下是该规则的代码:

You can use a @Rule for this. Here is the code for the rule:

import org.joda.time.DateTimeZone;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

public class UTCRule extends TestWatcher {

    private DateTimeZone origDefault = DateTimeZone.getDefault();

    @Override
    protected void starting( Description description ) {
        DateTimeZone.setDefault( DateTimeZone.UTC );
    }

    @Override
    protected void finished( Description description ) {
        DateTimeZone.setDefault( origDefault );
    }
}

您可以使用如下规则:

public class SomeTest {

    @Rule
    public UTCRule utcRule = new UTCRule();

    ....
}

SomeTest 中的每次测试之前,当前时区将是UTC,并且它将在每次测试后恢复默认时区。

This will change the current time zone to UTC before each test in SomeTest will be executed and it will restore the default time zone after each test.

如果要检查多个时区,请使用以下规则:

If you want to check several time zones, use a rule like this one:

import org.joda.time.DateTimeZone;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

public class TZRule extends TestWatcher {

    private DateTimeZone origDefault = DateTimeZone.getDefault();

    private DateTimeZone tz;

    public TZRule( DateTimeZone tz ) {
        this.tz = tz;
    }

    @Override
    protected void starting( Description description ) {
        DateTimeZone.setDefault( tz );
    }

    @Override
    protected void finished( Description description ) {
        DateTimeZone.setDefault( origDefault );
    }
}

将所有受影响的测试放在抽象基类中 AbstractTZTest 并对其进行扩展:

Put all the affected tests in an abstract base class AbstractTZTest and extend it:

public class UTCTest extends AbstractTZTest {
    @Rule public TZRule tzRule = new TZRule( DateTimeZone.UTC );
}

这将在 AbstractTZTest 与UTC。对于要测试的每个时区,您都需要另一个类:

That will execute all tests in AbstractTZTest with UTC. For each time zone that you want to test, you'll need another class:

public class UTCTest extends AbstractTZTest {
    @Rule public TZRule tzRule = new TZRule( DateTimeZone.forID( "..." );
}

因为继承了测试用例,仅此而已-您只需要定义规则即可。

Since test cases are inherited, that's all - you just need to define the rule.

以类似的方式,您可以移动系统时钟。一条规则,该规则调用 DateTimeUtils.setCurrentMillisProvider(...)以模拟测试在特定时间运行,并调用 DateTimeUtils.setCurrentMillisSystem()恢复默认设置。

In a similar way, you can shift the system clock. Use a rule that calls DateTimeUtils.setCurrentMillisProvider(...) to simulate that the test runs at a certain time and DateTimeUtils.setCurrentMillisSystem() to restore the defaults.

注意:您的提供商将需要一种使时钟计时或所有新的 DateTime 实例将具有相同的值,每次调用 getMillis()时,我通常将值提前一毫秒。

Note: Your provider will need a way to make the clock tick or all new DateTime instances will have the same value. I often advance the value by a millisecond each time getMillis() is called.

注2:仅适用于joda-time,不影响 new java.util.Date()

Note 2: That only works with joda-time. It doesn't affect new java.util.Date().

注3:您不能不再并行运行这些测试。它们必须按顺序运行,否则其中一个将很可能在运行另一个测试时恢复默认时区。

Note 3: You can't run these tests in parallel anymore. They must run in sequence or one of them will most likely restore the default timezone while another test is running.

这篇关于如何编写单元测试,以确保我的基于日期/时间的代码在所有时区均可使用,而无论是否启用DST?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆