Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单元测试节点时间别名日期时区_C#_Unit Testing_Nodatime - Fatal编程技术网

C# 单元测试节点时间别名日期时区

C# 单元测试节点时间别名日期时区,c#,unit-testing,nodatime,C#,Unit Testing,Nodatime,我正在为我的扩展方法进行单元测试 public static DateTimeZone GetDateTimeZone(this IDateTimeZoneProvider dateTimeZoneProvider, String timezoneId) { DateTimeZone dateTimeZone; if ((dateTimeZone = dateTimeZoneProvider.GetZoneOrNull(timezoneId)) != null)

我正在为我的扩展方法进行单元测试

public static DateTimeZone GetDateTimeZone(this IDateTimeZoneProvider dateTimeZoneProvider, String timezoneId)
{
    DateTimeZone dateTimeZone;
    if ((dateTimeZone = dateTimeZoneProvider.GetZoneOrNull(timezoneId)) != null)
        return dateTimeZone;    

    // Continues to try and map from TimeZoneInfo if dateTimeZone == null
}
当单元测试此方法时,测试失败,因为返回了DateTimeZone Id的别名

[TestMethod]
public void GetDateTimeZone_DateTimeZoneProviderHasTimezoneIdAsAlias_ReturnsDateTimeZone()
{
    var expectedTimezoneId = "America/New_York";
    var timezoneId = "US/Eastern";
    var dateTimeZone = _dateTimeZoneProvider.GetDateTimeZone(timezoneId); 

    Assert.AreEqual(expectedTimezoneId, dateTimeZone.Id);
}
正如您所看到的,我期待着Zone Id列中的内容,但是返回的是别名US/Eastern。 这尤其令人惊讶,因为关于GetZoneOrNull的文档 请注意,如果提供的ID是别名,则这可能会返回与请求的ID不同的DateTimeZone

阅读后,还要注意,对于相同ID的连续请求,不需要此方法返回相同的DateTimeZone实例;但是,为给定ID返回的所有实例必须进行相等比较。, 我想,也许别名DateTimeZone会等同于无关联

[TestMethod]
public void GetDateTimeZone_DateTimeZoneProviderHasTimezoneIdAsAlias_ReturnsDateTimeZone()
{
    var expectedDateTimeZone = _dateTimeZoneProvider.GetZoneOrNull("America/New_York");
    var timezoneId = "US/Eastern";
    var dateTimeZone = _dateTimeZoneProvider.GetDateTimeZone(timezoneId);

    Assert.AreEqual(expectedDateTimeZone, dateTimeZone);
}
但事实并非如此。调用扩展方法的代码实际上并不关心Id,因为它使用DateTimeZone将LocalTime转换为Utc

IDateTimeZoneProvider dateTimeZoneProvider = DateTimeZoneProviders.Tzdb;
var dateTimeZone = dateTimeZoneProvider.GetDateTimeZone(timezoneId);

var zonedDateTime = dateTimeZone.AtLeniently(localDateTime);
return zonedDateTime.ToDateTimeUtc(); 
因此,它将采用localDateTime时的当前偏移量。但是,出于单元测试的目的,我不能像美国/纽约的例子那样只检查偏移量,因为它有时是-5,有时是-4。在单元测试中断言它是-5或-4并不是一种洁净的感觉。我应该如何测试别名DateTimeZone

使现代化 下面是使用已知偏移量的特定日期和时间更新的单元测试

[TestMethod]
public void GetDateTimeZone_DateTimeZoneProviderHasTimezoneIdAsAlias_ReturnsDateTimeZone()
{
    var expectedOffset = Offset.FromHours(-5);
    var specificDateTimeWithKnownUtcOffset = new DateTime(2020, 1, 15, 8, 29, 15, DateTimeKind.Utc);
    var instant = Instant.FromDateTimeUtc(specificDateTimeWithKnownUtcOffset);
    var timezoneId = "US/Eastern";
    var dateTimeZone = _dateTimeZoneProvider.GetDateTimeZone(timezoneId);

    Assert.AreEqual(expectedOffset, dateTimeZone.GetUtcOffset(instant));
}

看了代码之后,我们可能想稍微修改一下文档。TzdbDateTimeZoneSource的当前行为是返回具有请求ID的DateTimeZone,但它使用与规范ID关联的数据

我认为这实际上并没有违反记录在案的行为——即传递别名可能会为您提供一个具有规范ID的区域——但这充其量只是一种误导

我可能会编写测试,要么不依赖于任何一种行为,要么依赖于当前的行为——这在未来的版本中不太可能改变。保留通过的身份证感觉更好。我需要研究是否有任何情况下,我们实际上想要返回一个具有规范ID的区域,但我怀疑我们可以将文档压缩到3.0

如果您想编写能够同时处理这两个问题的测试,那么只需检查返回ID的规范ID是否与传递ID的规范ID相同——但老实说,这似乎有些过分


请注意,UTC-4或UTC-5的偏移量不是任意的-您可以很容易地编写一个使用特定时区ID和本地日期/时间的测试,并期望在此基础上有一个给定的时刻。

查看了代码后,我们可能需要稍微修改文档。TzdbDateTimeZoneSource的当前行为是返回具有请求ID的DateTimeZone,但它使用与规范ID关联的数据

我认为这实际上并没有违反记录在案的行为——即传递别名可能会为您提供一个具有规范ID的区域——但这充其量只是一种误导

我可能会编写测试,要么不依赖于任何一种行为,要么依赖于当前的行为——这在未来的版本中不太可能改变。保留通过的身份证感觉更好。我需要研究是否有任何情况下,我们实际上想要返回一个具有规范ID的区域,但我怀疑我们可以将文档压缩到3.0

如果您想编写能够同时处理这两个问题的测试,那么只需检查返回ID的规范ID是否与传递ID的规范ID相同——但老实说,这似乎有些过分


请注意,UTC-4或UTC-5的偏移量不是任意的-您可以很容易地编写一个使用特定时区ID和本地日期/时间的测试,并期望在此基础上得到一个给定的时刻。

这可能没有多大帮助,但通常我会伪造提供者并使用垃圾数据。您不需要测试microsofts提供程序是否返回了预期的结果,他们会进行测试。您只需要测试代码是否调用提供程序并返回提供程序返回的结果。为什么需要从UTC转换DateTime对象?ToString方法自动将LocalTime Zone应用于ToString方法。DateTime对象标准是在UTC中的机器之间传输。我只想在您的代码中使用UTC时间,但从字符串输入并输出到字符串的情况除外。我不是将DateTime转换为UTC,而是将NodeTime的LocalDateTime转换为UTC中的DateTime。@jdweng:将所有内容都视为UTC而不进一步考虑是一种危险的做法。能够在时区之间转换肯定是一种很有价值的能力。你看,嗯。我对这种行为也感到惊讶,因为美国/纽约没有被归还。这可能帮不了什么忙,但我通常会伪造提供者并使用垃圾数据。你不知道吗

如果要测试microsofts提供程序是否返回预期结果,他们会进行测试。您只需要测试代码是否调用提供程序并返回提供程序返回的结果。为什么需要从UTC转换DateTime对象?ToString方法自动将LocalTime Zone应用于ToString方法。DateTime对象标准是在UTC中的机器之间传输。我只想在您的代码中使用UTC时间,但从字符串输入并输出到字符串的情况除外。我不是将DateTime转换为UTC,而是将NodeTime的LocalDateTime转换为UTC中的DateTime。@jdweng:将所有内容都视为UTC而不进一步考虑是一种危险的做法。能够在时区之间转换肯定是一种很有价值的能力。你看,嗯。我对这种行为也感到惊讶,因为美国/纽约没有被归还。将进行调查。我遇到的问题是,由于单元测试正在测试,如果Id没有从GetZoneOrNull返回,它将命中代码,尝试将TimeZoneInfo时区Id映射到规范Id,并且是否可以通过dateTimeZoneProvider上的Id索引获取它。因为我实际上并没有为这个测试选择一个日期或时间,它可能会失败,这取决于它运行的时间。我想我唯一的选择是选择测试只有一个可能的偏移量的时区。@ScubaSteve:我不确定你的意思-GetZoneOrNull将为别名和规范ID返回一个非空值,所以这应该可以。GetDateTimeZone方法不检查返回的DateTimeZone中的ID是否是请求的ID,并且可能不应该检查该ID。该方法不应用任何日期/时间-因此编写两个测试或一个参数化测试,在美国/东部和美国/纽约传递称为GetDateTimeZone,并在每种情况下将返回的区域应用于固定的日期/时间是合理的。@ScubaSteve:基本上,您没有显示任何使用当前日期和时间的代码,因此您没有显示任何依赖于运行时间的代码。如果你的测试中还有其他代码,我会建议你修复它——或者用代码问另一个问题,然后问如何去除它。我明白我的错误了。在我的测试中,我查看了偏移属性,认为这些属性的值会随着测试运行的时间而变化。我没有看到GetUtcOffset,它允许我选择特定的日期和时间,在该日期和时间我可以知道偏移量是多少。@ScubaSteve:不确定您指的是哪个偏移量属性-DateTimeZone不具有任何依赖于当前日期/时间的属性。除了系统时钟,野田佳彦的时间只有一小部分依赖于系统时钟,那就是我们需要猜测系统时区的时候,因为TimeZoneInfo.Local没有给我们一个有用的ID。我遇到的问题是,因为单元测试正在测试如果ID没有从GetZoneOrNull返回,如果它可以通过dateTimeZoneProvider上的Id索引获得它,那么它将命中尝试将TimeZoneInfo时区Id映射到规范Id的代码。因为我实际上并没有为这个测试选择一个日期或时间,它可能会失败,这取决于它运行的时间。我想我唯一的选择是选择测试只有一个可能的偏移量的时区。@ScubaSteve:我不确定你的意思-GetZoneOrNull将为别名和规范ID返回一个非空值,所以这应该可以。GetDateTimeZone方法不检查返回的DateTimeZone中的ID是否是请求的ID,并且可能不应该检查该ID。该方法不应用任何日期/时间-因此编写两个测试或一个参数化测试,在美国/东部和美国/纽约传递称为GetDateTimeZone,并在每种情况下将返回的区域应用于固定的日期/时间是合理的。@ScubaSteve:基本上,您没有显示任何使用当前日期和时间的代码,因此您没有显示任何依赖于运行时间的代码。如果你的测试中还有其他代码,我会建议你修复它——或者用代码问另一个问题,然后问如何去除它。我明白我的错误了。在我的测试中,我查看了偏移属性,认为这些属性的值会随着测试运行的时间而变化。我没有看到GetUtcOffset,它允许我选择特定的日期和时间,在该日期和时间我可以知道偏移量是多少。@ScubaSteve:不确定您指的是哪个偏移量属性-DateTimeZone不具有任何依赖于当前日期/时间的属性。除了系统时钟,野田佳彦的时间只有一小部分依赖于系统时钟,那就是我们需要猜测系统时区的时候,因为TimeZoneInfo.Local没有给我们一个有用的ID。