Ger*_*och 9 string testing parameters null
通常使用带有字符串参数的方法的类必须再次验证null或为空,例如:
public class MyClass {
public void MyMethod(string param){
if(string.IsNullOrEmpty(param)){
throw new ArgumentNullException(...);
}
//...
}
}
Run Code Online (Sandbox Code Playgroud)
很明显,该方法的行为对于两个(无效)值都是相同的.这是一种非常常见的情况,在测试这些方法时,我总是怀疑如何做到这一点.我总是为这些案例创建两个单独的测试:
[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("");
//...
}
Run Code Online (Sandbox Code Playgroud)
}
但我看到太多的冗余.那些测试完全相同,唯一的区别是传递给方法的参数.这非常困扰我,因为我必须为每个字符串参数创建两个测试.具有3个参数的方法将仅具有6个测试以测试参数.
我认为这是测试这些参数的正确方法,但是如果我知道99%的字符串参数将以相同的方式进行验证,那么测试它们是否为null(或为空)并不是更好,并假设其中的行为另一种情况会是一样的吗?
我想知道你对此的看法.我知道我所要求的更多是技术意见而不是技术问题,但我认为测试社区可能会对这种情况说些有趣的话.
谢谢!
Jon*_*eet 12
就个人而言,我会考虑对所有参数使用单个测试.这不遵循单元测试的正常教条,但它增加了测试的可读性(通过最小化专用于非常重复的情况的测试代码的数量)并且没有太多的缺点.是的,如果测试失败,你不知道在第一次失败后的所有检查是否也会失败 - 但这在实践中真的是一个问题吗?
重要的是要确保你有一个捷径来测试案件.例如,你可能会写这样的东西(如果你的单元测试框架还没有):
public static void ExpectException<T>(Action action) where T : Exception
{
try
{
action();
Assert.Fail("Expected exception " + typeof(T).Name);
}
catch (T exception)
{
// Expected
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以写:
[Test]
public void MyMethodFailsWithInvalidArguments()
{
ExpectException<ArgumentNullException>(() => myClass.MyMethod(null));
ExpectException<ArgumentException>(() => myClass.MyMethod(""));
}
Run Code Online (Sandbox Code Playgroud)
比使用单独的try/catch块,甚至使用ExpectedException属性和多个测试执行每个更简洁.
您可能希望在需要验证每种情况下都没有触及模拟对象(检查是否避免副作用)或可能会出现常见异常的情况时需要重载ArgumentNullException.
对于单参数方法,您甚至可以编写一个方法来封装您需要的内容:
public void ExpectExceptionForNullAndEmptyStrings(Action<string> action)
{
ExpectException<ArgumentNullException>(() => action(null));
ExpectException<ArgumentException>(() => action(""));
}
Run Code Online (Sandbox Code Playgroud)
然后用:
[Test]
public void MyMethodFailsWithInvalidArguments()
{
// This *might* work without the
ExpectExceptionForNullAndEmptyStrings(myClass.MyMethod);
}
Run Code Online (Sandbox Code Playgroud)
...对于具有单个参数但非void返回类型的方法可能是另一个.
虽然可能有点远:)