如何使用Java对自定义日期反序列化器进行单元测试

如何使用Java对自定义日期反序列化器进行单元测试,java,unit-testing,Java,Unit Testing,我刚开始学习单元测试 我想对自定义日期反序列化器进行单元测试,如下所示: CustomDateDeserializer.java import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterx

我刚开始学习单元测试

我想对自定义日期反序列化器进行单元测试,如下所示:

CustomDateDeserializer.java

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class CustomDateDeserializer extends JsonDeserializer {
    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {

        Long toParse = p.getLongValue();
        SimpleDateFormat format = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
        format.setTimeZone(TimeZone.getTimeZone("GMT+1"));

        String formattedActualDate = format.format(new Date(toParse));

        return formattedActualDate;
    }
}
最好的测试方法是什么?
非常感谢您的建议。

如果我理解得很好,您有一个JsonParser,您可以从中提取一个long并将其转换为可读的日期

首先,不要使用
Date
SimpleDateFormat
:它们已经过时了,
java.time
API比它们好得多。这就是我要用的

您需要的是模拟参数。
JsonParser
DeserializationContext
都是抽象类,因此很容易模拟它们

为了模拟,我们使用Mockito或Powermock等库

对于下面的示例,我使用了Mockito

CustomDateDeserializer deserializer;
JsonParser parser;
DeserializationContext context;

@BeforeEach
void setup() {
  deserializer = new CustomDateDeserializer();
  parser = mock(JsonParser.class);
  context = mock(DeserializationContext.class);
}

@Test
void testDeserialize() {
  when(parser.getLongValue()).thenReturn(12L*60*60*1000); // 1970-01-01T12:00:00.000Z
  
  String result = deserializer.deserialize(parser, context);
  
  assertEquals("01 Jan 1970 11:00:00 GMT+1");
}
但是您的实现使用了不推荐的API。。。您应该改用java.time。另外,请注意,Java允许您使返回类型比重写的方法更具体,因此让我们也重写您的方法:

class CustomDateDeserializer extends JsonDeserializer {
  static final ZoneOffset ZONE_OFFSET = ZoneOffset.of("UTC+01:00");
  static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd MMM yyyy HH:mm:ss z");

  @Override
  // Note the return-type is String, not Object
  public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    Instant instant = Instant.ofEpochMilli(p.getLongValue());
    LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZONE_OFFSET);
    return dateTime.format(FORMATTER);
  }
}

嗨,非常感谢你的回答。在
LocalDateTime-dateTime=LocalDateTime.ofEpoch(instant,ZONE\u OFFSET)中使用您的代码进行反序列化时,我有一个问题
ofEpoch函数带红色下划线,我无法使用它。你知道为什么吗?我还使用用于自定义反序列化类的导入更新了我的代码。@user9347049抱歉,这是我的一个错误。您必须使用
LocalDateTime.ofInstant
而不是
LocalDateTime.ofEpoch
,这是我的错误。谢谢。当我尝试用
stringresult=deserializer.deserialize(解析器,上下文)实现代码prom测试部分时,还有一个问题带红色下划线,表示:
所需类型:提供的字符串:对象资产质量(“1970年1月1日11:00:00 GMT+1”);`部分错误:
无法解析方法“assertEquals(java.lang.String)”
为什么?baeldung.com上的解释通常是有效的。但是他们的导航是次标准的,所以尝试搜索“junit baeldung”或任何主题,然后搜索“baeldung”,你会找到你大部分问题的答案。(你要知道,我和他们没有关系,我只是觉得他们做的很好。)我读了很多。好的,谢谢你!谢谢您的回答:)(1)不要使用
Date
SimpeDateFOrmat
。它们设计拙劣,早已过时。(2) 转向面向对象。不要用字符串表示日期和时间。使用
即时
。(3) 不要使用GMT偏移量,假装它是一个时区。使用适当的时区ID,例如非洲/阿尔及尔或非洲/突尼斯。