我怎样写单元测试,以确保我的基于日期/时间码适用于所有时区,并与输入/输出DST?(How do I

2019-06-25 01:33发布

我使用JodaTime 2.1和我在寻找一个模式的单元测试代码执行日期/时间的操作,以确保它的所有时区和独立的行为以及DST 。

特别:

  1. 我怎么能嘲笑系统时钟(所以我没有嘲笑一切,我所说的地方new DateTime()来获得当前的时间)
  2. 我该怎么办默认时区相同?

Answer 1:

您可以使用@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();

    ....
}

这将当前时区更改为UTC在每次测试之前SomeTest将被执行,每次测试后,将恢复默认的时区。

如果您想检查几个时区,使用类似这样的规则:

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并扩展它:

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

这将在执行所有测试AbstractTZTest与UTC。 对于要测试的每个时区,你需要另一个类:

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

由于测试用例继承,这就是 - 你只需要定义规则。

以类似的方式,可改变一个系统时钟。 使用调用规则DateTimeUtils.setCurrentMillisProvider(...)来模拟测试在一定的时间和运行DateTimeUtils.setCurrentMillisSystem()恢复默认设置。

注意:您的供应商将需要一种方法来使时钟滴答或所有新DateTime实例将具有相同的值。 我通常由毫秒每次推进值getMillis()被调用。

注2:只有具有乔达时间工作。 它不影响new java.util.Date()

注3:你已经无法并行运行这些测试。 他们必须按顺序运行或其他测试运行时,其中一人将最有可能恢复默认的时区。



Answer 2:

for (String zoneId : DateTimeZone.getAvailableIDs())
{
   DateTime testedDate1;
   DateTime testedDate2;
   try
   {
      final DateTimeZone tz = DateTimeZone.forID(zoneId);
      // your test with testedDate1 and testedDate2 
   }
   catch (final IllegalArgumentException e)
   {
      // catching DST problem
      testedDate1 = testetDate1.plusHours(1);
      testedDate2 = testetDate2.plusHours(1);
      // repeat your test for this dates
   }
}

改变单测试

DateTimeZone default;  

DateTimeZone testedTZ;

@Before
public void setUp()
{
   default = GateTimeZone.getDefault();
   DateTimeZone.setDefault
}  

@After
public void tearDown()
{
   default = GateTimeZone.setDefault();
   DateTimeZone.setDefault(testedTZ)
}   

@Test
public void test()
{
//...
}


文章来源: How do I write unit tests to make sure my date/time based code works for all time zones and with/out DST?