首页 > 解决方案 > EF 和 NPGSQL 之间的 DateTimeOffset 精度不匹配

问题描述

重现步骤

所以我有一个集成测试,它在 db 中创建一个用户,然后确认它是准确创建的。在此处查看测试和完整的工作存储库。

测试看起来像这样:

        [Test]
        public async Task AddPatientCommand_Adds_New_Patient_To_Db()
        {
            // Arrange
            var fakePatientOne = new FakePatientForCreationDto { }.Generate();

            // Act
            var command = new AddPatientCommand(fakePatientOne);
            var patientReturned = await SendAsync(command);
            var patientCreated = await ExecuteDbContextAsync(db => db.Patients.SingleOrDefaultAsync());

            // Assert
            patientReturned.Should().BeEquivalentTo(fakePatientOne, options =>
                options.ExcludingMissingMembers());
            patientCreated.Should().BeEquivalentTo(fakePatientOne, options =>
                options.ExcludingMissingMembers());
        }

它可以与 sql server 一起工作并通过,并且似乎也可以在这里工作,但是由于看起来像DateTimeOffset?属性上的精度问题,测试失败了。

我希望测试能够通过,但似乎 EF 中的 datetimeoffset 和 npgsql 之间的精度不匹配。正如您在错误消息中看到的,该Dob属性是匹配的,除了2EF 对象中的额外内容。我希望 npgsql 检索到的值匹配。

关于这里发生了什么以及我如何能够解决它的任何想法?认为这可能是库中的错误。

Message: 
    Expected member Dob to be <2021-03-22 22:45:15.0749082 -4h>, but found <2021-03-22 22:45:15.074908 -4h>.
    
    With configuration:
    - Use declared types and members
    - Compare enums by value
    - Try to match member by name
    - Without automatic conversion.
    - Be strict about the order of items in byte arrays
    
  Stack Trace: 
    LateBoundTestFramework.Throw(String message)
    TestFrameworkProvider.Throw(String message)
    CollectingAssertionStrategy.ThrowIfAny(IDictionary`2 context)
    EquivalencyValidator.AssertEquality(EquivalencyValidationContext context)
    ObjectAssertions.BeEquivalentTo[TExpectation](TExpectation expectation, Func`2 config, String because, Object[] becauseArgs)
    AddPatientCommandTests.AddPatientCommand_Adds_New_Patient_To_Db() line 28
    GenericAdapter`1.BlockUntilCompleted()
    NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaitable)
    AsyncToSyncAdapter.Await(Func`1 invoke)
    TestMethodCommand.RunTestMethod(TestExecutionContext context)
    TestMethodCommand.Execute(TestExecutionContext context)
    <>c__DisplayClass1_0.<Execute>b__0()
    BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)

标签: c#postgresqlentity-framework-core

解决方案


有时你可以忽略像这样微小的不精确的事情(百万分之一秒)。

patientReturned.Should().BeEquivalentTo(fakePatientOne,
            opt => opt
                .Using<DateTime>(su => su.Subject.Should().BeCloseTo(su.Expectation, 10)) <-- 10 ms is close enough
                   .WhenTypeIs<DateTime>()

推荐阅读