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

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

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

    public class DateTimeConverter : JsonConverter<DateTime>
    {
        public override DateTime Read(ref Utf8JsonReader reader,Type typeToConvert,JsonSerializerOptions options)
        {
            return DateTime.Parse(reader.GetString());
        }

        public override void Write(Utf8JsonWriter writer,DateTime value,JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString("yyyy-MM-ddThh:mm:ss.ffffff"));
        }
    }

问题在于此转换器不会截断尾随零,而实际响应会截断。因此,测试失败的几率为十分之一。

这是测试失败:

    [Fact]
    public async Task GetUsers()
    {
        using var clientFactory = new ApplicationFactory<Startup>();
        using var client = clientFactory.Createclient();
        using var context = clientFactory.CreateContext();

        var user1 = context.Users.Add(new User()).Entity;
        var user2 = context.Users.Add(new User()).Entity;
        context.SaveChanges();

        var users = new List<User> { user1,user2 };
        var jsonSerializerOptions = new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        };
        var serializedUsers = JsonSerializer.Serialize(users,jsonSerializerOptions);

        var response = await client.Getasync("/users");

        var responseBody = await response.Content.ReadAsStringAsync();
        Assert.Equal(serializedUsers,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"···

我没有在控制器的实际实现中配置任何序列化选项。

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

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

1。使用UTC时间戳

我真的鼓励您将时间戳记为UTC。

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

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

产生

{"UpdatedAtUtc":"2019-11-06T02:41:45.4610928Z"}

2。使用您的转换器

var x = new { UpdatedAt = DateTime.Now };

JsonSerializerOptions options = new JsonSerializerOptions();
options.Converters.Add(new DateTimeConverter());

Console.WriteLine(JsonSerializer.Serialize(x,options));
{"UpdatedAt":"2019-11-06T12:50:48.711255"}

3。使用DateTimeKind.Unspecified

class X { public DateTime UpdatedAt {get;set;}}

public static void Main()
{
    var localNow = DateTime.Now;
    var x = new X{ UpdatedAt = localNow };

    Console.WriteLine(JsonSerializer.Serialize(x));
    x.UpdatedAt = DateTime.SpecifyKind(localNow,DateTimeKind.Unspecified);
    Console.WriteLine(JsonSerializer.Serialize(x));

产生

{"UpdatedAt":"2019-11-06T12:33:56.2598121+10:00"}
{"UpdatedAt":"2019-11-06T12:33:56.2598121"}

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


注意微秒和DateTimeKind

随着测试的进行,您可能会发现放入数据库的对象与从数据库中检索到的对象之间的时间戳不匹配。

根据您的设置,DateTime可能以LocalUnspecified的形式从数据库中检索(即使您将Utc放入数据库中),也可能会失去一些精度( db列将仅存储它的最大恢复大小(可能是毫秒)。

,

您要做的是获取DateTime“往返”表示形式,可以使用以下方法完成:

https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings#Roundtrip

var d = DateTime.Now.ToString("o");

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

https://docs.microsoft.com/en-us/dotnet/api/system.datetime.kind?view=netframework-4.8

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

https://dotnetfiddle.net/ccGSEO

本文链接:https://www.f2er.com/3155452.html

大家都在问