【问题标题】:DateTimeFormatter.ofPattern(...) returns null on jenkins, while locally it works [duplicate]DateTimeFormatter.ofPattern(...) 在jenkins上返回null,而在本地它可以工作[重复]
【发布时间】:2020-12-15 16:42:05
【问题描述】:

当我们使用 Jacoco 覆盖工具在 Jenkins 上运行测试时,在 IDE 上本地运行的两个测试在 Jenkins 上失败了。

Jenkins Stacktrace

java.lang.NullPointerException: formatter
    at java.util.Objects.requireNonNull(Objects.java:228)
    at java.time.LocalDateTime.format(LocalDateTime.java:1751)
    at valid.package.MyUtils.generateReferenceId(MyUtils.java:356)

测试类

public class MyUtils{

       private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyyyyHHmmss");

//method under test
public static String generateReferenceId(StationState stationState) {
        StringBuilder referenceId = new StringBuilder();
        referenceId.append(String.format("%04d", stationState.getLocationId()));
        referenceId.append(String.format("%06d", stationState.getStoreNbr()));
        referenceId.append(String.format("%02d", stationState.getSessionId()));
        referenceId.append(LocalDateTime.now().format(formatter));  //null was found here - line 356
        return referenceId.toString();
    }

测试

@RunWith(PowerMockRunner.class)
@PrepareForTest({
        MyUtils.class
})
class MyUtilsTest{
@Test
        public void generateReferenceId_whenGenerate_shouldReturnNotNull() {
            //given
            //when
            String referenceId = MyUtils.generateReferenceId(stationState);
            //then
            // assertions
        }

第二个测试的方法在不同的类中,除了不同的模式看起来相同。

private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS";
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT);

所以没有理由把它放在这里。 所以:

  1. 我想知道 DateTimeFormatter.ofPattern(..) 如何返回 null 对于私有静态决赛?

  2. 你认为这是因为 PowerMockito 与 Jacoco on-the-fly 仪器一起使用时会导致问题 PowerMockito with Jacoco。我们正在降低覆盖率,如中所述 上面的链接。

  3. 当我内联时

    私有静态最终 DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT);

到 generateReferenceId() 方法

referenceId.append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("ddMMyyyyHHmmss")));

对 Jenkins 的测试不再抛出 NPE。

环境详情:

本地环境:Java 版本 1.8.0.271,Win 10 操作系统,国家/地区 PL

Jenkins 版本:

[java]      [echo] *       Run By: jenkins on Wednesday, December 9, 2020 11:07:40 AM UTC
[java]      [echo] *          JVM: Oracle Corporation v25.231-b11
[java]      [echo] *           OS: Linux amd64 v4.14.203-156.332.amzn2.x86_64

Jenkins 在英国的 AWS 上。

【问题讨论】:

  • 可以在本地用jacoco运行测试吗?
  • 是的。它在本地通过了所有测试。但与 Jenkins 一样,覆盖率有所降低。
  • 你的模拟工具会不会干扰?只是一个想法。
  • 确保它没有在测试代码中明确显示。我们不是在嘲笑 DateTimeFormatter、LocalDateTime.now() 或与之相关的任何东西。
  • 当我内联私有静态最终 DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT);对 Jenkins 的 generateReferenceId() 方法测试不再抛出 NPE。

标签: java jenkins null jacoco datetimeformatter


【解决方案1】:

解决方法

我在一个经过测试的方法中嵌入了常量 DateTimeFormatter.ofPattern(FORMAT),它不再在 Jenkins 上抛出 NullPointerException。

public static String generateReferenceId(StationState stationState) {
        StringBuilder referenceId = new StringBuilder();
        referenceId.append(String.format("%04d", stationState.getLocationId()));
        referenceId.append(String.format("%06d", stationState.getStoreNbr()));
        referenceId.append(String.format("%02d", stationState.getSessionId()));
        referenceId.append(LocalDateTime.now().format(DateTimeFormatter.ofPattern(FORMAT)));
        return referenceId.toString();
    }

也许这不是解决方案,因为我没有找到根本原因,但可以肯定这是一个简单的解决方法。

为了确保我已经进行了测试并首先在第一个失败的测试方法中进行了内联并且它通过了,而另一个带有常量的方法失败了。在我在第二个测试方法中内联它之后也通过了。

【讨论】:

    猜你喜欢
    • 2023-03-17
    • 1970-01-01
    • 2018-03-04
    • 2014-09-09
    • 2018-06-21
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多