简单的 NUnit 测试失败,因为没有抛出异常(抛出测试之外)
Simple NUnit test fail because exception is not thrown ( out of the test is thrown)
我正在创建一个扩展泛型方法 Apply,它做什么并不重要,主要问题是我无法理解如何测试它,像 ApplyOnNullFunctionThrow 这样的简单测试并没有说不抛出异常,但是如果我 运行 来自 main 的“手动测试”,它会抛出
主要:
class Program
{
static void Main(string[] args)
{
foreach (var i in first.Apply(second,f)) Console.WriteLine("{0}", i);
Console.ReadLine();
}
}
扩展方法:
public static class Applier
{
public static IEnumerable<T> Apply<T>(this IEnumerable<T> first, IEnumerable<T> second,Func<T,T,T> f)
{
if(f == null ) throw new ArgumentNullException();
if (null==first || null==second) throw new ArgumentNullException();
var x=second.GetEnumerator();
foreach (var item in first)
{
yield return x.MoveNext() ? f(item, x.Current) : f(item, default);
}
while (x.MoveNext())
{
yield return f(default, x.Current);
}
}
}
测试:
class ApplierTests
{
[TestCase(new[]{1,2,3},new[]{10,20,30},null)]
public void ApplyOnNullFunctionThrow<T>(IEnumerable<T> first, IEnumerable<T> second,Func<T,T,T> f)
{
Assert.Throws<ArgumentNullException>(() => first.Apply(second, f));
}
}
在您的 Apply
方法中,您有 yield
关键字,这意味着序列的元素将一次返回一个。因此,当您仅使用 yield
关键字调用该方法时,它实际上什么都不做,只是 returns 一个迭代器 (IEnumerable<T>
),您可以在 [=15] 中使用它=].这里的底线是,在返回的迭代器上调用 MoveNext
之前,不会执行原始 Apply
方法的代码,因此它不会抛出异常。要解决此问题,您可能需要一个没有 yield
关键字的包装器:
public static IEnumerable<T> Apply<T>(this IEnumerable<T> first, IEnumerable<T> second,Func<T,T,T> f)
{
if(f == null ) throw new ArgumentNullException();
if (null==first || null==second) throw new ArgumentNullException();
return ApplyInternal(first, second, f);
}
private static IEnumerable<T> ApplyInternal<T>(...) {
var x=second.GetEnumerator();
foreach (var item in first)
{
yield return x.MoveNext() ? f(item, x.Current) : f(item, default);
}
while (x.MoveNext())
{
yield return f(default, x.Current);
}
}
除了创建私有方法,您还可以使用 C# 7 feature called local functions 作为替代方法
另见,当你调用Main
中的方法时抛出异常,因为你使用foreach
语句中的方法的结果被编译成重复调用[=17] =].
我正在创建一个扩展泛型方法 Apply,它做什么并不重要,主要问题是我无法理解如何测试它,像 ApplyOnNullFunctionThrow 这样的简单测试并没有说不抛出异常,但是如果我 运行 来自 main 的“手动测试”,它会抛出
主要:
class Program
{
static void Main(string[] args)
{
foreach (var i in first.Apply(second,f)) Console.WriteLine("{0}", i);
Console.ReadLine();
}
}
扩展方法:
public static class Applier
{
public static IEnumerable<T> Apply<T>(this IEnumerable<T> first, IEnumerable<T> second,Func<T,T,T> f)
{
if(f == null ) throw new ArgumentNullException();
if (null==first || null==second) throw new ArgumentNullException();
var x=second.GetEnumerator();
foreach (var item in first)
{
yield return x.MoveNext() ? f(item, x.Current) : f(item, default);
}
while (x.MoveNext())
{
yield return f(default, x.Current);
}
}
}
测试:
class ApplierTests
{
[TestCase(new[]{1,2,3},new[]{10,20,30},null)]
public void ApplyOnNullFunctionThrow<T>(IEnumerable<T> first, IEnumerable<T> second,Func<T,T,T> f)
{
Assert.Throws<ArgumentNullException>(() => first.Apply(second, f));
}
}
在您的 Apply
方法中,您有 yield
关键字,这意味着序列的元素将一次返回一个。因此,当您仅使用 yield
关键字调用该方法时,它实际上什么都不做,只是 returns 一个迭代器 (IEnumerable<T>
),您可以在 [=15] 中使用它=].这里的底线是,在返回的迭代器上调用 MoveNext
之前,不会执行原始 Apply
方法的代码,因此它不会抛出异常。要解决此问题,您可能需要一个没有 yield
关键字的包装器:
public static IEnumerable<T> Apply<T>(this IEnumerable<T> first, IEnumerable<T> second,Func<T,T,T> f)
{
if(f == null ) throw new ArgumentNullException();
if (null==first || null==second) throw new ArgumentNullException();
return ApplyInternal(first, second, f);
}
private static IEnumerable<T> ApplyInternal<T>(...) {
var x=second.GetEnumerator();
foreach (var item in first)
{
yield return x.MoveNext() ? f(item, x.Current) : f(item, default);
}
while (x.MoveNext())
{
yield return f(default, x.Current);
}
}
除了创建私有方法,您还可以使用 C# 7 feature called local functions 作为替代方法
另见,当你调用Main
中的方法时抛出异常,因为你使用foreach
语句中的方法的结果被编译成重复调用[=17] =].