C# 如何在ASP.NET Core 3.0中编写涉及DateTime Json序列化的集成测试?

C# 如何在ASP.NET Core 3.0中编写涉及DateTime Json序列化的集成测试?,c#,asp.net-core,asp.net-core-3.0,json-serialization,C#,Asp.net Core,Asp.net Core 3.0,Json Serialization,我正在为ASP.NET Core 3.0中的Api控制器编写集成测试。该测试针对的是以实体列表响应的路由。当我尝试对响应内容进行断言时,DateTime属性序列化的方式存在分歧 我已尝试在测试中使用自定义JsonConverter: 公共类DateTimeConverter:JsonConverter { 公共覆盖日期时间读取(参考Utf8JsonReader reader,键入typeToConvert,JsonSerializerOptions选项) { return DateTime.Pa

我正在为ASP.NET Core 3.0中的Api控制器编写集成测试。该测试针对的是以实体列表响应的路由。当我尝试对响应内容进行断言时,DateTime属性序列化的方式存在分歧

我已尝试在测试中使用自定义JsonConverter:

公共类DateTimeConverter:JsonConverter
{
公共覆盖日期时间读取(参考Utf8JsonReader reader,键入typeToConvert,JsonSerializerOptions选项)
{
return DateTime.Parse(reader.GetString());
}
公共重写无效写入(Utf8JsonWriter编写器、日期时间值、JsonSerializerOptions选项)
{
writer.WriteStringValue(value.ToString(“yyyy-MM-ddth:MM:ss.ffffff”);
}
}
问题在于,此转换器不会截断尾随的零,而实际响应会截断尾随的零。因此,测试失败的几率为十分之一

这是失败的测试:

[事实]
公共异步任务GetUsers()
{
使用var clientFactory=new ApplicationFactory();
使用var client=clientFactory.CreateClient();
使用var context=clientFactory.CreateContext();
var user1=context.Users.Add(new User()).Entity;
var user2=context.Users.Add(new User()).Entity;
SaveChanges();
var users=新列表{user1,user2};
var jsonSerializerOptions=新的jsonSerializerOptions
{
PropertyNamingPolicy=JsonNamingPolicy.CamelCase
};
var serializedUsers=JsonSerializer.Serialize(用户,jsonSerializerOptions);
var response=wait client.GetAsync(“/users”);
var responseBody=await response.Content.ReadAsStringAsync();
Assert.Equal(序列化dusers、responseBody);
Assert.Equal(HttpStatusCode.OK,response.StatusCode);
}
我希望测试能够通过,但我得到了以下错误:

  Error Message:
   Assert.Equal() Failure
                                 ↓ (pos 85)
Expected: ···1-05T22:14:13.242771-03:00","updatedAt"···
Actual:   ···1-05T22:14:13.242771","updatedAt"···
我没有在控制器的实际实现中配置任何序列化选项

如何正确实施此集成测试?是否有一种简单的方法可以使用real controller的相同选项在测试中序列化列表?

1。使用UTC时间戳 我真的鼓励您将时间戳保留为UTC

var x = new { UpdatedAtUtc = DateTime.UtcNow };

Console.WriteLine(JsonSerializer.Serialize(x));
产生

{"UpdatedAtUtc":"2019-11-06T02:41:45.4610928Z"}
{"UpdatedAt":"2019-11-06T12:33:56.2598121+10:00"}
{"UpdatedAt":"2019-11-06T12:33:56.2598121"}
2.使用你的转换器 3.使用
DateTimeKind.Unspecified
产生

{"UpdatedAtUtc":"2019-11-06T02:41:45.4610928Z"}
{"UpdatedAt":"2019-11-06T12:33:56.2598121+10:00"}
{"UpdatedAt":"2019-11-06T12:33:56.2598121"}

顺便说一句,您应该在测试代码和测试代码中使用相同的Json选项


注意微秒和
DateTimeKind
随着测试的深入,您可能会发现放入数据库的对象与从数据库检索到的等价对象之间的时间戳不匹配


根据您的设置,
DateTime
s可以作为
Local
Unspecified
从数据库中检索(即使您将Utc输入数据库),并且可能会丢失一些精度(db列将只存储其最大恢复值,可能是毫秒)

您要做的是获取日期时间“往返”表示,这可以通过使用:

如果仍然发现使两种日期时间格式相同的问题,则可以使用“System.DateTime.Kind”属性

下面是我制作的一个简单示例,您可以在线运行它:


当我没有在服务器或测试中指定任何转换器时,就会出现显示的错误消息。哦,好的,我看错了帖子谢谢你的回答。您让我意识到EF Core使用DateTimeKind.Unspecified实例化DateTime,但当我手动实例化新对象时,我使用的是DateTimeKind.Local。我将构造函数更改为
var now=DateTime.SpecifyKind(DateTime.UtcNow,DateTimeKind.Unspecified),我现在不需要自定义转换器。我不知道“往返”格式,很高兴知道,谢谢!这种差异确实是由于System.DateTime.Kind属性造成的,因此在比较新实例化的对象(DateTimeKind.Local)和从数据库检索的对象(DateTimeKind.Unspecified)时存在不匹配。
{"UpdatedAt":"2019-11-06T12:33:56.2598121+10:00"}
{"UpdatedAt":"2019-11-06T12:33:56.2598121"}
var d = DateTime.Now.ToString("o");