【问题标题】:Trying to expose additional information when using xUnit Assert.Throws在使用 xUnit Assert.Throws 时尝试公开其他信息
【发布时间】:2013-05-04 23:34:04
【问题描述】:

我只是设置了一些第一个单元测试,我不太明白我试图实现的目标(使用我当前的测试结构)可以完成,这意味着我不确定我的方法是否测试不正确,或者只是对 xUnit 的限制。

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

所以,我在 Test 类上有一个私有字段:

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,那么它就会通过测试,这不对。但是,由于参数是接口,我无法实例化它们的新实例。所以任何想要复制测试代码的人,我都不会这样做。不是在这里寻找该问题的解决方案。

【问题讨论】:

    标签: unit-testing xunit


    【解决方案1】:

    Assert.Throws 只是在 try catch 块中执行委托的辅助方法。你不必使用它,你可以用你自己的实现来替换它。比如:

    [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);
           }
        }
    }
    

    这只是一个想法。您可以在自己的静态断言方法中重构它...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      相关资源
      最近更新 更多