我正在尝试测试一个非常简单的功能。它返回包含一些指定数字的数字。如果第一个参数是null
,它将抛出ArgumentNullException
。
不幸的是,Assert.Throws
说,没有引发预期的异常,并且测试失败。当我尝试调试测试时,它不会进入我的方法。 ArgumentException
也是如此。
仅最后两个测试失败,其他测试成功。
我要测试的功能
/// <summary>
/// Filter given numbers and return only numbers containing the specified digit.
/// </summary>
/// <param name="numbers">The numbers to be filtered.</param>
/// <param name="digit">The digit which should be found.</param>
/// <returns>Numbers that contains the digit.</returns>
/// <exception cref="ArgumentException"> Thrown if the digit value isn't between 0 and 9.</exception>
/// <exception cref="ArgumentNullException"> Thrown if numbers are null.</exception>
public static IEnumerable<int> FilterDigits(IEnumerable<int> numbers, byte digit)
{
if (numbers == null)
{
throw new ArgumentNullException();
}
foreach (int number in numbers)
{
if (number.ContainsDigit(digit))
{
yield return number;
}
}
}
/// <summary>
/// Check whether the number contains the given digit.
/// </summary>
/// <param name="number">The number which can contain the digit.</param>
/// <param name="digit">The digit to be found.</param>
/// <returns>True if the number contains the digit, else false.</returns>
/// <exception cref="ArgumentException"> Thrown if the digit value isn't between 0 and 9.</exception>
/// <example> ContainsDigit(10, 1) -> true </example>
/// <example> ContainsDigit(10, 2) -> false </example>
private static bool ContainsDigit(this int number, byte digit)
{
if (!char.TryParse(digit.ToString(), out char digitChar))
{
throw new ArgumentException("The digit should be from 0 to 9.");
}
string numberString = number.ToString();
foreach (char ch in numberString)
{
if (ch == digitChar)
{
return true;
}
}
return false;
}
我的考试班:
[TestFixture]
public class DigitsFilterTests
{
[TestCase(new int[] { 1, 4, 23, 346, 7, 23, 87, 71, 77 }, 7, ExpectedResult = new int[] { 7, 87, 71, 77 })]
[TestCase(new int[] { 345, 4, 0, 90, 709 }, 0, ExpectedResult = new int[] { 0, 90, 709})]
public IEnumerable<int> FilterDigits_NumbersContainDigit(int[] numbers, byte digit)
=> DigitsFilter.FilterDigits(numbers, digit);
[TestCase(new int[] { 1, 4, 222, 9302 }, 7, ExpectedResult = new int[] { })]
[TestCase(new int[] { 345, 4, 354, 25, 5 }, 0, ExpectedResult = new int[] { })]
public IEnumerable<int> FilterDigits_NumbersNotContainDigit(int[] numbers, byte digit)
=> DigitsFilter.FilterDigits(numbers, digit);
[TestCase(new int[] { }, 0, ExpectedResult = new int[] { })]
public IEnumerable<int> FilterDigits_EmptyList(int[] numbers, byte digit)
=> DigitsFilter.FilterDigits(numbers, digit);
[Test]
public void FilterDigits_NullNumbers_ArgumentNullException()
=> Assert.Throws<ArgumentNullException>(() => DigitsFilter.FilterDigits(null, 5));
[Test]
public void FilterDigits_InvalidDigit_ArgumentException()
=> Assert.Throws<ArgumentException>(() => DigitsFilter.FilterDigits(new int[] { }, 10));
}
答案 0 :(得分:6)
您的方法是使用yield return
构建的枚举。棘手的是,除非您枚举,否则什么都不会发生。
因此,您必须确保测试枚举内容:
[Test]
public void FilterDigits_NullNumbers_ArgumentNullException()
=> Assert.Throws<ArgumentNullException>(() => DigitsFilter.FilterDigits(null, 5).ToList());
此外,您的第二次测试将以任何一种方式失败,因为如果ContainsDigit
为空,则不会达到numbers
。
如果要修复方法内部的行为,则需要将其分为两个部分:
public static IEnumerable<int> FilterDigits(IEnumerable<int> numbers, byte digit)
{
if (numbers == null)
{
throw new ArgumentNullException();
}
return FilterDigitsImpl(numbers, digit);
}
private static IEnumerable<int> FilterDigitsImpl(IEnumerable<int> numbers, byte digit)
{
foreach (int number in numbers)
{
if (number.ContainsDigit(digit))
{
yield return number;
}
}
}
如果您的C#版本足够新,则可以使用本地函数合并这两种方法:
public static IEnumerable<int> FilterDigits(IEnumerable<int> numbers, byte digit)
{
if (numbers == null)
{
throw new ArgumentNullException();
}
IEnumerable<int> FilterDigitsImpl()
{
foreach (int number in numbers)
{
if (number.ContainsDigit(digit))
{
yield return number;
}
}
}
return FilterDigitsImpl();
}