4

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

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

    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>

ThrowIfNull<>我在 Stack Overflow 上看到的扩展方法的一种变体。

在为此编写测试用例时,我首先编写了一个助手:

    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)(或者是吗?)。我不能用这种方式测试匿名对象吗?

4

1 回答 1

11

object确实有default(T),只是碰巧有null。这与您使用不可为空值类型的其他测试用例不同。这就是为什么你得到一个NullReferenceException而不是你所期望的。

如果你更换

self.Equals(default(T))

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

你应该开始得到预期的ArgumentException.

于 2013-04-23T18:49:18.447 回答