简体   繁体   English

在Jenkins中,DateFormat UnitTest失败,但本地失败

[英]DateFormat UnitTest fails in Jenkins but not locally

I've made a unit-test of a Service, when I execute the Jenkins job, every test method pass correctly, except one. 我已经对服务进行了单元测试,当我执行Jenkins作业时,除一个测试方法外,其他所有测试方法均正确通过。
But this test method, works on my machine, both with Eclipse and using the mvn command. 但是这种测试方法可以在我的机器上使用Eclipse和mvn命令。

    // TARGET_RUN_DATE_OF_YEAR = "2018-01-01"
    @Test
    public void dateToTimestamp() {
        Service service = getService();

        String df = "YYYY-MM-dd";
        String invalid = "INVALID";

        // Check success
        Timestamp timestamp = service.dateToTimestamp(TARGET_RUN_DATE_OF_YEAR, df);
        Assert.assertEquals(service.getTodayTimestamp(), timestamp); // <-- Fail here
        // Check failure
        Assert.assertNull(service.dateToTimestamp(TARGET_RUN_DATE_OF_YEAR, invalid));
        Assert.assertNull(service.dateToTimestamp(invalid, df));
    }

The Service have mulitple methods: 该服务有多种方法:

  • getTodayTimestamp give today Timestamp, this method is tested, it works on my machine and on Jenkins. getTodayTimestamp提供今天的时间戳,此方法已经过测试,适用于我的机器和Jenkins。
  • dateToTimestamp takes a date and a dateFormat as Strings, and returns the date as a Timestamp, this method is the one not working. dateToTimestamp一个日期和一个dateFormat作为字符串,然后将日期作为时间戳返回,该方法不起作用。

The dateToTimestamp method in the Service: 服务中的dateToTimestamp方法:

    private Timestamp dateToTimestamp(String date, DateFormat df) throws ParseException {
        return new Timestamp(df.parse(date).getTime());
    }

    @Override
    public Timestamp dateToTimestamp(String date, String dateFormatString) {
        try {
            DateFormat df = new SimpleDateFormat(dateFormatString);
            return dateToTimestamp(date, df);
        } catch (Exception e) {
            log.warn("Exception during conversion of date to timestamp, exception : {}", e);
            return null;
        }
    }

As I previously said, the test work perfectly on my pc, but not on Jenkins (adding the @Ignore annotations to this method, makes the job successful). 就像我之前说过的那样,该测试可以在我的PC上完美运行,但不能在Jenkins上完美运行(向此方法添加@Ignore批注使该工作成功完成)。
When launching the job, I get this error: 启动作业时,出现以下错误:

Failed tests: dateToTimestamp(com.test.service.ServiceImplTest): expected:<2018-01-01 00:00:00.0> but was:<2017-12-31 00:00:00.0> 测试失败:dateToTimestamp(com.test.service.ServiceImplTest):预期:<2018-01-01 00:00:00.0>,但是:<2017-12-31 00:00:00.0>

What I can assure, is that even in Jenkins, the dateToTimestamp method takes the parameters TARGET_RUN_DATE_OF_YEAR , which is "2018-01-01" and the dateFormart String as "YYYY-MM-dd" . 我可以保证,是,即使在詹金斯dateToTimestamp方法需要的参数TARGET_RUN_DATE_OF_YEAR ,这是"2018-01-01"和dateFormart字符串为"YYYY-MM-dd" But still returns 2017-12-31 00:00:00.0 as Timestamp. 但仍会返回2017-12-31 00:00:00.0作为时间戳。

Any ideas? 有任何想法吗?

java.time java.time

I am assuming that you wanted a Timestamp for use with your SQL database. 我假设您想将Timestamp用于SQL数据库。 Don't use Timestamp for that in 2019. That class is poorly designed and long outdated. 请勿在2019年使用Timestamp 。该类的设计不佳,而且早已过时。

  • If the datatype on the SQL side is timestamp with time zone (which it should be for a timestamp), use OffsetDateTime in Java. 如果SQL端的数据类型是timestamp with time zone (应该是时间戳), OffsetDateTime在Java中使用OffsetDateTime
  • If on the SQL side you need a mere timestamp (without time zone), use LocalDateTime in Java. 如果在SQL端仅需要timestamp (无时区),请在Java中使用LocalDateTime

Code example: 代码示例:

    String dateString = "2018-01-01";
    OffsetDateTime odt = LocalDate.parse(dateString)
            .atStartOfDay()
            .atOffset(ZoneOffset.UTC);

    System.out.println(odt);

Output is: 输出为:

2018-01-01T00:00Z 2018-01-01T00:00Z

Now you can pass your OffsetDateTime to JDBC using something like: 现在,您可以使用以下方式将OffsetDateTime传递给JDBC:

    yourPreparedStatement.setObject(4, odt);

What went wrong in your code? 您的代码出了什么问题?

I believe that you are experiencing the combination of two issues: 我相信您正在遇到两个问题的结合:

  • Using uppercase YYYY in your format pattern string is incorrect. 在格式模式字符串中使用大写YYYY是不正确的。 Uppercase Y is for week based year and only useful with a week number. 大写字母Y用于基于周的年份,仅与星期数一起使用。 With the old and troublesome SimpleDateFormat you would have needed lowercase y for year. 如果使用旧的麻烦的SimpleDateFormat ,则一年中需要使用小写的y
  • (The JVMs on) your machine and the Jenkins server have different default locales. 您的机器和Jenkins服务器(上的JVM)具有不同的默认语言环境。

To demonstrate: 展示:

    String dateString = "2018-01-01";
    String dateFormatString = "YYYY-MM-dd"; // Incorrect format pattern string
    DateFormat df = new SimpleDateFormat(dateFormatString);
    System.out.println(df.parseObject(dateString));

Output on my computer (Danish locale, Europe/Copenhagen time zone): 我的计算机上的输出(丹麦语言环境,欧洲/哥本哈根时区):

Mon Jan 01 00:00:00 CET 2018 CET 2018年1月1日星期一00:00:00

However if I first do this: 但是,如果我首先这样做:

    Locale.setDefault(Locale.US);

— then the output from the above snippet is different, namely: —那么以上代码段的输出是不同的,即:

Sun Dec 31 00:00:00 CET 2017 2017年12月31日星期日00:00:00 CET

What happens is that SimpleDateFormat gives up on determining an exact date from week based year, month and day of month and instead just gives you the first date of the week based year. 发生的是, SimpleDateFormat放弃了从基于周的年,月和日中确定确切的日期,而只是给您基于周的年的第一个日期。 It's typical behaviour of SimpleDateFormat to give you a result that cannot be right and nevertheless pretend that all is well. SimpleDateFormat的典型行为是给您带来不正确的结果,但假装一切都很好。 In some locales the week begins on Monday, and you get Mon Jan 01, which coincidentally agrees with your string. 在某些地区,星期从星期一开始,您会遇到1月1日星期一,这恰好与您的字符串一致 In other locales, such as the US, the week starts on Sunday, so instead you get Sun Dec 31 of the previous year. 在其他地区,例如美国,一周从星期日开始,所以您将前一年的12月31日定为星期日。

Link 链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM