我应该为参数例外编写测试吗?

时间:2011-09-02 13:34:19

标签: c# unit-testing tdd

在应用TDD时,您是否创建了验证参数的预期异常(ArgumentException,ArgumentNullException,InvalidOperation等)的测试,或者只是那些“已知”的测试,例如,CustomerDelinquentException?

等于什么,gethashcode覆盖?我将如何测试gethashcode?

由于

3 个答案:

答案 0 :(得分:5)

我总是测试我在方法中抛出的任何异常,包括ArgumentNullExceptionArgumentException等。我发现最好对它们进行测试,并且它们很容易编写。这样,如果有人移除那些守卫,那么测试就会破坏,你知道。

    [TestMethod]
    [ExpectedException(typeof(ArgumentNullException))]
    public void ToSetOnNullThrows()
    {
        List<string> list = null;
        var target = list.ToHashSet();
    }

至于GetHashCode()Equals()我还会测试这些如果你覆盖它们。对于GetHashCode(),一个简单的测试是创建两个等效对象(在哈希代码中使用相同的值)并证明两个对象生成的哈希码是相同的。

    [TestMethod]
    public void GetHashCodeSameKeysAreSameTest()
    {
        var key = new CompositeKey<string, int>("A", 13);
        var otherKey = new CompositeKey<string, int>("A", 13);

        Assert.AreEqual(key.GetHashCode(), otherKey.GetHashCode());
    }

您可以尝试来测试两个非等效对象返回不同的哈希码,但您必须确保您使用的值不仅仅是冲突。这在很大程度上取决于您在GetHashCode()中编码的算法。

    [TestMethod]
    public void GetHashCodeDifferentKeysAreMostLikelyDifferentTest()
    {
        var key = new CompositeKey<string, int>("A", 13);
        var otherKey = new CompositeKey<string, int>("A", 14);

        Assert.AreNotEqual(key.GetHashCode(), otherKey.GetHashCode());
    }

对于Equals()测试,具有相同字段的两个等效对象在true上返回Equals(),在两个非等效对象上返回false

    [TestMethod]
    public void EqualsTest()
    {
        var key = new CompositeKey<string, int>("A", 13);
        var otherKey = new CompositeKey<string, int>("A", 13);

        Assert.IsTrue(key.Equals(otherKey));
    }

    [TestMethod]
    public void NotEqualsTest()
    {
        var key = new CompositeKey<string, int>("A", 13);
        var otherKey = new CompositeKey<string, int>("A", 15);

        Assert.IsFalse(key.Equals(otherKey));
    }

为了更有趣,我也喜欢单独测试DateTime依赖的东西。这有点难,但如果方法的行为取决于DateTime,我仍然想要对它们进行单元测试。因此,您可以创建一个DateTime生成器委托,默认返回DateTime.Now,但要将其设置为可以将生成器设置为特定的DateTime。因为我从事金融业,所以我的工作范围很大,而且很多逻辑依赖于上市前,上市后时间等......

public class SomeClassThatDependsOnCurrentTime
{
    internal Func<DateTime> NowGenerator { get; set; }

    public SomeClassThatDependsOnCurrentTime()
    {
        // default in constructor to return DateTime.Now
        NowGenerator = () => DateTime.Now;
    }

    public bool IsAfterMarketClose()
    {
        // call the generator instead of DateTime.Now directly...
        return NowGenerator().TimeOfDay > new TimeSpan(16, 0, 0);
    }
}

然后,您只需设置一个单元测试来注入特定的日期时间。

答案 1 :(得分:0)

如果您的代码测试参数并抛出异常,那么您应该测试这些异常。如果没有或者另外,您应该使用无效值测试代码以查看发生的情况。

当你期望两个对象相等时,你也应该测试equals,那种测试gethashcode。

答案 2 :(得分:0)

是。不要忘记,单元测试也可以作为一种文档形式。它向使用您的组件的下一个开发人员或客户端显示他们调用的函数或方法的前提条件。