【发布时间】:2015-03-05 14:16:58
【问题描述】:
所以我是单元测试的新手(迟到了,但我至少在这里)。我将我的几个 ASP.NET MVC Web 应用程序使用的一些通用代码提取到一个或多个类库中。我现在正在为其中的一些代码编写单元测试……其中大部分实际上是 IDataReader 上的扩展方法(目的是针对 OdbcDataReader 使用)。在下面的代码中,扩展方法扩展了对象,以便我可以实际编写单元测试。我曾尝试使用 Moq 模拟 IDataReader 来测试扩展方法,但我读过这是不可能的。无论如何,这并不是这个问题的真正意义。
这是我的问题。我有一个名为“GetSafeDecimal”的方法。目的是这样使用:
dr.getSafeDecimal(dr["FieldValue"])
方法定义如下:
public static decimal GetSafeDecimal(this object rdr, object value)
{
decimal result = 0;
decimal temp = -1;
if (value == null || value is DBNull)
result = 0;
else if (decimal.TryParse(value.ToString(), out temp))
result = temp;
else if (value is string)
{
String s = Convert.ToString(value) ?? string.Empty;
s = s.Replace(" ", "");
if (String.IsNullOrEmpty(s) ||
!decimal.TryParse(s, out temp))
{
result = 0;
}
else
{
result = decimal.Parse(s);
}
}
return result;
}
我的实际问题:我在单元测试中看到大量重复。设置并不难。我只是为我正在测试的每个输入编写一个单元测试。这是单元测试的“正确”方法吗?
以下是我对上述方法的一些单元测试:
[TestMethod]
public void GetSafeDecimalNullReturns0()
{
decimal result = "".GetSafeDecimal(null);
Assert.AreEqual(result , 0);
}
[TestMethod]
public void GetSafeDecimalIntReturnsDecimalValue()
{
decimal result = "".GetSafeDecimal(5);
Assert.AreEqual(result, 5);
}
[TestMethod]
public void GetSafeDecimalStringReturns0()
{
decimal result = "".GetSafeDecimal("asdf");
Assert.AreEqual(result, 0);
}
[TestMethod]
public void GetSafeDecimalStringSpecialCharactersReturns0()
{
decimal result = "".GetSafeDecimal("a_ s)@#$df");
Assert.AreEqual(result, 0);
}
[TestMethod]
public void GetSafeDecimalIntStringReturns0()
{
decimal result = "".GetSafeDecimal("2 3 5");
Assert.AreEqual(result, 235);
}
[TestMethod]
public void GetSafeDecimalDecimalReturnsDecimal()
{
decimal result = "".GetSafeDecimal(3.14M);
Assert.AreEqual(result, 3.14M);
}
[TestMethod]
public void GetSafeDecimalDoubleReturnsDecimal()
{
decimal result = "".GetSafeDecimal(3.14d);
Assert.AreEqual(result, 3.14M);
}
@Sebastian 的解决方案是正确的。切换到 nunit 后,我的测试现在看起来像:
public class SafeDecimalTestData
{
public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(null).Returns(0);
yield return new TestCaseData(5).Returns(5);
yield return new TestCaseData("asdf").Returns(0);
yield return new TestCaseData("a_ s)@#$df").Returns(0);
yield return new TestCaseData("2 3 5").Returns(235);
yield return new TestCaseData(3.14m).Returns(3.14m);
yield return new TestCaseData(3.14m).Returns(3.14d);
yield return new TestCaseData(new DateTime(2015,1,1)).Returns(0);
}
}
}
[Test, TestCaseSource(typeof(SafeDecimalTestData), "TestCases")]
public decimal GetSafeDecimalTestInputs(object input)
{
return "".GetSafeDecimal(input);
}
我以这种方式编写测试,而不是仅仅使用 TestCase 属性,因为测试不允许我使用像 3.14d、3.14m 或 DateTime 这样的值。我想要一个解决方案,无论我测试的是哪种数据,我都可以在所有测试中始终如一地使用它。该解决方案来自 NUnit 文档:
【问题讨论】:
标签: c# unit-testing tdd