当前位置: 首页 > 知识库问答 >
问题:

使用Java8个日期/时间类编写和测试方便方法

易流觞
2023-03-14

我有一些使用Calendars编写的旧的方便方法,我想更新它们以使用Java8中引入的Java.time.*类。我类中的一些方法获取当前时间甚至只是当前小时的数量。

我计划为每个方法编写两个变体:一个假设时区是这台计算机上定义的默认时区,另一个允许用户指定所需的时区。

我想弄清楚两件主要的事情:

  1. 如何在我的方法中获取当前时间戳
  2. 如何使用不同的当前时间戳源对结果进行单元测试

关于方法本身,我倾向于创建一个ZoneDateTime,如下所示:

LocalDateTime currentDateTime = LocalDateTime.now();
ZoneId timeZoneDefault = ZoneId.systemDefault(); 
ZonedDateTime currentZonedDateTimeDefault = ZonedDateTime.of(currentDateTime, timeZoneDefault);

然后我会使用DateTimeFormatter来获得我真正关心的部分结果。例如,如果我想从24小时开始计算当前小时,然后从12小时开始计算,我会这样做:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("kk");
System.out.println("currentHour (24 hour clock): " + currentZonedDateTimeDefault.format(fmt));
DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("hh a");
System.out.println("currentHour (12 hour clock): " + currentZonedDateTimeDefault.format(fmt2));

到目前为止,这还可以吗?或者我应该使用另一种方法,也许是使用Instant?

我的主要问题是找出一种不同的方法来获取单元测试的当前时间,以便将预期结果与实际结果进行比较。我一直在读关于时钟和瞬间等等的书,读得越多,我就越困惑。有些方法似乎是从同一个来源获取当前时间,因此它们可能会显示预期结果始终与实际结果相同,但这两种方法可能以相同的方式错误。

有人能告诉我在给定时区计算当前时间的最佳方法吗?这种方法与我在方法中使用的方法不同?

更新:我正在研究我的方便方法,并在每个方法中使用它,从获取当前日期和时间开始:

    LocalDateTime now = LocalDateTime.now();
    ZonedDateTime nowLocalTimeZone = ZonedDateTime.of(now, ZoneId.systemDefault());

然后,我通过这样的代码获得我真正想要的日期/时间部分:

try {
        DateTimeFormatter format = DateTimeFormatter.ofPattern(MONTH_NUMBER_FORMAT);
        return Integer.parseInt(nowLocalTimeZone.format(format));
    }
    catch (DateTimeParseException excp) {
        throw excp;         
    }

请注意,在这些方法中,所有内容都基于LocalDateTime。now()没有指定时钟。

在我的单元测试中,我把它作为一个类变量:

    private Clock localClock = Clock.fixed(Instant.now(), ZoneId.systemDefault());

在典型的单元测试中,我有这样的代码:

@Test
@DisplayName ("getCurrentMonthNumberLocal()")
void testGetCurrentMonthNumberLocal() {

    LocalDateTime now = LocalDateTime.now(localClock);
    ZonedDateTime nowLocalTimeZone = ZonedDateTime.of(now, ZoneId.systemDefault());

    //Normal cases
    assertEquals(nowLocalTimeZone.getMonthValue(), CurrentDateTimeUtils.getCurrentMonthNumberLocal());
}

请注意,这种方法涉及使用名为localClock的固定时钟作为预期结果的源。

当我运行测试时,预期的结果与实际结果相匹配(至少对于我迄今为止运行的几个类来说是这样的,它们查找年份和月份数)。

这种方法是否确保我从两个不同的来源获得当前时间,以便比较有效?或者我是否有效地从完全相同的来源获得相同的信息,例如我计算机上的系统时钟?

我非常希望从方法中获得的日期/时间来自不同的来源,而不是用于确定单元测试中预期结果的日期/时间,这样我就可以确定这是一个有效的测试,否则,我认为测试这些方法没有多大意义。(我想我可以只显示每个函数的结果,看看它是否大致正确。很容易判断年份、月份和日期是否正确,除非你可能非常接近那一年、月份或日期的末尾,在这种情况下,你可能实际上看到了不同时区的值,却不知道。)

共有1个答案

牛迪
2023-03-14

在您的测试中(并且仅在测试期间!)设置便利课程使用的时钟,以便您可以独立于计算机时钟预测期望/预期结果:

public class ConvenienceTest {

    @Test
    public void testGetLocalHour() {
        Convenience underTest = new Convenience();

        ZoneId zone = ZoneId.of("America/Los_Angeles");

        ZonedDateTime fixedZdt = ZonedDateTime.now(zone).withHour(0);
        underTest.setClock(Clock.fixed(fixedZdt.toInstant(), zone));
        assertEquals("24", underTest.getLocalHour24HourClock());

        fixedZdt = fixedZdt.withHour(1);
        underTest.setClock(Clock.fixed(fixedZdt.toInstant(), zone));
        assertEquals("01", underTest.getLocalHour24HourClock());

        fixedZdt = fixedZdt.withHour(23);
        underTest.setClock(Clock.fixed(fixedZdt.toInstant(), zone));
        assertEquals("23", underTest.getLocalHour24HourClock());

        // TODO test with other time zones
    }

}

为了实现这一点,当然需要你的便利课程能够接受一个时钟,并使用它:

public class Convenience {

    private Clock clock = Clock.systemDefaultZone();

    /** For testing only. Sets the clock from which to get the time. */
    void setClock(Clock clockForTest) {
        this.clock  = clockForTest;
    }

    public String getLocalHour24HourClock() {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("kk");
        ZonedDateTime zdt = ZonedDateTime.now(clock);
        return zdt.format(fmt);
    }

}

有了这个实现,测试就通过了我的计算机。

退一步:如果你的便利方法只是java之上的一层薄薄的话。随着时间的推移,您可能会开始考虑单元测试有多大的价值。如果它正在做一些实际的工作(比如上面例子中的格式化,经常出错的事情),那么测试是有价值的,但是如果一个方法只是从对java的单个调用中返回一个值。时间,你可能不需要测试。你不应该测试java。时间,最好只有你自己的代码。

 类似资料:
  • } ---编辑1--更改 根据注释,断言是失败的。

  • 我有下面的类,我测试了method1,并模拟了method2和method3。我只测试这样的用例:*如果method2调用是OK,那么==>OK*如果method2抛出NotFoundException,method3返回OK==>OK*如果method2抛出NotFoundException,method3抛出ServiceException==>ServiceException确实抛出了 为了

  • 本文向大家介绍Java日期时间使用方法汇总,包括了Java日期时间使用方法汇总的使用技巧和注意事项,需要的朋友参考一下 一、Java中的日期概述 日期在Java中是一块非常复杂的内容,对于一个日期在不同的语言国别环境中,日期的国际化,日期和时间之间的转换,日期的加减运算,日期的展示格式都是非常复杂的问题。  在Java中,操作日期主要涉及到一下几个类:  1、java.util.Date     

  • 我需要一些解释为什么这个代码不编译: 错误: 类型Duration中的(TemporalAmount)方法不适用于参数(ChronoUnit) 正如本文所述: public static Duration from(TemporalAmount amount)从时间量中获取持续时间的实例。这将根据指定的金额获得持续时间。TemporalAmount表示一个时间量,可以是基于日期的,也可以是基于时间

  • 我有一个测试类,其中我有大约10个单元测试用例。在本文中,我创建了一个mock方法,它只在10个测试用例中的2个中有用。 因此,从技术上讲,我希望对8个测试用例执行方法,并对其中2个测试用例进行模拟。 有没有办法做到这一点?

  • 也许有人能给我举个例子?我在问自己,新的日期和时间API的改进来自哪里。