【问题标题】:default(T) behaviour on anonymous types匿名类型的默认(T)行为
【发布时间】:2013-04-24 03:16:14
【问题描述】:

我正在针对我们的核心框架编写单元测试,并且遇到了这个问题。

我们有一个如下所示的扩展方法:

    public static T ThrowIfDefault<T>(this T self, string variableName)
    {
        if (self.Equals(default(T)))
            throw new ArgumentException(string.Format("'{0}' cannot be default(T)", variableName));
        return self;
    }   // eo ThrowIfDefault<T>

(我在 Stack Overflow 上看到的 ThrowIfNull&lt;&gt; 扩展方法的变体。

在为此写一个测试用例的时候,我先写了一个helper:

    public void ThrowIfDefaultTestHelper<T>(T value)
    {
        // unit test *itself* requires that a value be specified!!
        Assert.AreNotEqual(default(T), value);

        // Good test
        GenericExtensionMethods.ThrowIfDefault(value, "value");

        // Bad test
        try
        {
            GenericExtensionMethods.ThrowIfDefault(default(T), "value");
        }
        catch (ArgumentException)
        {
            // Expected result
        }
        catch (Exception)
        {
            throw;
        }
    }

然后是以下内容:

    [TestMethod()]
    public void ThrowIfDefaultTest()
    {
        ThrowIfDefaultTestHelper<int>(10);
        ThrowIfDefaultTestHelper<Guid>(Guid.NewGuid());
        ThrowIfDefaultTestHelper<DateTime>(DateTime.Now);
        ThrowIfDefaultTestHelper<object>(new { Name = "Test" });    // anonymous object
    }

单元测试在最后一个失败,因为NullReferenceException 被抛出,因为我猜object 没有default(T)(或者是吗?)。我不能用这种方式测试匿名对象吗?

【问题讨论】:

  • 在一个唯一目的是检查null的方法中使用实例方法(Equals)有点奇怪...
  • @DanielHilgarth,绝对!当别人看到时,人们会错过的小东西是非常明显的。因此,使用单元测试是个好主意……我们都是人类 :)

标签: c# unit-testing generics


【解决方案1】:

object 确实有default(T),它恰好是null。这与您使用不可为空值类型的其他测试用例不同。这就是为什么您会收到 NullReferenceException 而不是您所期望的。

如果你替换

self.Equals(default(T))

EqualityComparer<T>.Default.Equals(obj, default(T))

您应该开始收到预期的ArgumentException

【讨论】:

  • 掴额头这完全有道理。谢谢。
  • 此外,这是一个完美的例子,说明了为什么单元测试对明显的“永远有效”的代码很重要:)
  • 最后一点,只是为了清楚起见-我确实在那里传递了string,它不是值类型,并且测试通过了。因此,我假设default(T) for string is non-null?
  • @Moo-Juice:在您提供的代码中,您不会将default(T)T == typeof(string) 一起传递。如果你这样做,你会得到NullReferenceException,就像你对其他所有引用类型一样。 default(string)null
  • @DanielHilgarth,说得好——所以可以肯定地说它会死在那里而不是最后一个。我的错。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 2011-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多