我应该如何测试方法中的null和/或空字符串参数?

时间:2009-05-30 20:54:38

标签: string testing parameters null

通常使用带有字符串参数的方法的类必须再次验证null或为空,例如:

public class MyClass {

    public void MyMethod(string param){

        if(string.IsNullOrEmpty(param)){
            throw new ArgumentNullException(...);
        }
        //...
    }
}

很明显,两个(无效)值的方法行为相同。这是一种非常常见的情况,在测试这些方法时,我总是怀疑如何做到这一点。我总是为这些案例创建两个单独的测试:

[TestClass]
public class Tests {

    [TestMethod]
    public void MyMethod_should_fail_if_param_is_null(){
        //...
        myclass.MyMethod(null);
        //...
    }

    [TestMethod]
    public void MyMethod_should_fail_if_param_is_empty(){
        //...
        myclass.MyMethod("");
        //...
    }

}

但我看到太多的冗余。那些测试完全相同,唯一的区别是传递给方法的参数。这非常困扰我,因为我必须为每个字符串参数创建两个测试。具有3个参数的方法仅有6个测试来测试参数。

我认为这是测试这些参数的正确方法,但是如果我知道99%的字符串参数将以相同的方式验证,那么测试它们是否为空(或为空)并不是更好在另一种情况下的行为会是一样的吗?

我想知道你对此的看法。我知道我所要求的更多是技术意见而不是技术问题,但我认为测试社区可能会对这种情况有所了解。

谢谢!

2 个答案:

答案 0 :(得分:12)

就我个人而言,考虑对所有参数使用单个测试。这不遵循单元测试的正常教条,但它增加了测试的可读性(通过最小化专用于非常重复的情况的测试代码的数量)并且没有太多的缺点。是的,如果测试失败,你不知道第一次失败之后的所有检查是否也会失败 - 但实际上确实是一个问题吗?

重要的是要确保你有一个捷径来测试案件。例如,你可能会写这样的东西(如果你的单元测试框架还没有):

public static void ExpectException<T>(Action action) where T : Exception
{
    try
    {
        action();
        Assert.Fail("Expected exception " + typeof(T).Name);
    }
    catch (T exception)
    {
        // Expected
    }
}

然后你可以写:

[Test]
public void MyMethodFailsWithInvalidArguments()
{
    ExpectException<ArgumentNullException>(() => myClass.MyMethod(null));
    ExpectException<ArgumentException>(() => myClass.MyMethod(""));
}

比使用单独的try / catch块,甚至使用ExpectedException属性和多个测试更简洁。

对于您还想要验证在每种情况下都没有触及任何模拟对象(以检查是否避免副作用)或可能是ArgumentNullException等常见异常的重载的情况,您可能需要重载。 / p>

对于单参数方法,您甚至可以编写一个方法来准确地封装您需要的方法:

public void ExpectExceptionForNullAndEmptyStrings(Action<string> action)
{
    ExpectException<ArgumentNullException>(() => action(null));
    ExpectException<ArgumentException>(() => action(""));
}

然后用:

来调用它
[Test]
public void MyMethodFailsWithInvalidArguments()
{
    // This *might* work without the 
    ExpectExceptionForNullAndEmptyStrings(myClass.MyMethod);
}

...也许是另一个用于具有单个参数但是非void返回类型的方法。

虽然可能会有点远:)

答案 1 :(得分:-3)

如果您使用Java和JUnit,则可以使用此语法

@Test(expected = IllegalArgumentException.class)
public void ArgumentTest() {
   myClass.MyMethod("");
   myClass.MyMethod(null);
}