2013-05-10 40 views
0

我只是设置了一些第一次单元测试,我不能完全看到我试图实现(我目前的测试结构)可以完成,这意味着我不确定我的测试方法是不正确的,还是仅限于xUnit。试图暴露额外的信息,当使用xUnit Assert.Throws

我正在测试我的MVC Controllers,并且希望确保它们全都提供了一个ArgumentNullException,如果它们构造为传递null作为参数(它们通过Castle在现实世界中解决)。

所以,我一直在测试类的私人领域:

private IEnumerable<Type> ControllerTypes = typeof(MyBaseController).Assembly.GetTypes().Where(t => IsController(t)); 

然后,我的测试方法:

[Fact] 
    public void EnsureControllersThrowIfProvidedWithNull() { 
     foreach (var controller in ControllerTypes) { 
      var ctrs = GetConstructorsForType(controller); 
      if (null == ctrs || !ctrs.Any()) { //if the controller has no constructors, that's fine, we just skip over it 
       continue; 
      } 
      var ctr = ctrs.ElementAt(0); 
      var ctrParamsAsNull = ctr.GetParameters().Select(p => (object)null); 
      Assert.Throws<ArgumentNullException>(() => { 
       ctr.Invoke(ctrParamsAsNull.ToArray()); 
      }); 
     } 
    } 

因此,这是所有工作正常,我跑的测试运行,而且我的Controllers之一在传递null时不会抛出ArgumentNullException,太好了,我的测试失败了,但我不知道从给定的输出是哪个控制器。

我确实知道如何通过测试来调试,看看哪些是失败的,并且可以手动通过我的所有控制器来检查它是哪一个,但知道哪个控制器失败是很有用的。

还是我使用单元测试错在这里? (注意,还有另外一个测试可以确保每个控制器只有一个公共构造函数,所以只要第一次测试通过,我就可以确定我在正确构造函数的时候触发了这个构造函数)。

感谢

注: 有在测试中的逻辑漏洞,这意味着它不能完全覆盖我所期待太,只要它抛出了至少1的ArgumentNullException的论点,那么它会通过测试,这是不正确的。然而,由于参数是接口,我不能实例化它们的新实例。所以任何想复制测试代码的人,我都不会这样做。在这里找不到解决此问题的解决方案。

回答

2

Assert.Throws只是在try catch块内部执行delegate的helper方法。你不必使用它,你可以用你自己的实现来替换它。例如:

[Fact] 
public void EnsureControllersThrowIfProvidedWithNull() { 
    foreach (var controller in ControllerTypes) { 
     var ctrs = GetConstructorsForType(controller); 
     if (null == ctrs || !ctrs.Any()) { //if the controller has no constructors, that's fine, we just skip over it 
      continue; 
     } 
     var ctr = ctrs.ElementAt(0); 
     var ctrParamsAsNull = ctr.GetParameters().Select(p => (object)null); 
     book ok = false; 
     try 
     { 
      ctr.Invoke(ctrParamsAsNull.ToArray()); 
     } 
     catch(ArgumentNullException) 
     { 
      //you get exception you expected so continue 
      ok = true; 
     } 
     if(!ok) 
     { 
      // you didn't get exception so throw your own exception with message that contains controller type name 
      throw new Exception(String.Format("Ctor on type {0} did not throw ArgumentNullException",controller.Name); 
     } 
    } 
} 

这只是作为想法的工作。你可以重构你自己的静态断言方法...