如何在C#的NUnit测试中传递对象并测试Income.Create方法
解决NUnit测试自定义类对象的问题
原测试代码的问题
- 测试方法参数未配置数据源:NUnit不会自动识别带参数的测试方法,必须通过
[TestCase]或[TestCaseSource]指定测试数据 - 循环逻辑错误:遍历列表时调用
bLL.Create(income)而非bLL.Create(item),导致始终使用同一个对象(即使参数能传入) - 业务代码语法错误:原Create方法的if条件多了一个右括号,修正后应为:
if ((income.Date is null) || (income.Amount == 0) || (income.Payee_ID == 0))
正确的测试实现方式
方式1:使用[TestCaseSource]实现参数化测试
这种方式适合将测试数据与测试逻辑分离,方便扩展测试用例:
namespace Test_Layer { [TestFixture] public class NunitTests { // 定义合法测试用例数据源 private static IEnumerable<Income> ValidIncomeTestCases() { yield return new Income { Date = "01-01-2000", Amount = 1000, Payee_ID = 1, Payor = "Bob", Description = "Contract no 1" }; yield return new Income { Date = "02-01-2000", Amount = 1500, Payee_ID = 2, Payor = "Jimmy", Description = "Contract no 2" }; } // 定义非法测试用例数据源(覆盖必填项缺失场景) private static IEnumerable<TestCaseData> InvalidIncomeTestCases() { // Date为null的情况 yield return new TestCaseData(new Income { Date = null, Amount = 1000, Payee_ID = 1 }).Returns((false, "Fill all the required fields!")); // Amount为0的情况 yield return new TestCaseData(new Income { Date = "01-01-2000", Amount = 0, Payee_ID = 1 }).Returns((false, "Fill all the required fields!")); // Payee_ID为0的情况 yield return new TestCaseData(new Income { Date = "01-01-2000", Amount = 1000, Payee_ID = 0 }).Returns((false, "Fill all the required fields!")); } // 测试合法输入的场景 [Test] [TestCaseSource(nameof(ValidIncomeTestCases))] public void IncomeCreate_ValidInput_ReturnsSuccess(Income income) { var bLL = new Family_Budget_BLL.IncomeBLL(); var (successResult, errorMessage) = bLL.Create(income); Assert.Multiple(() => { Assert.That(successResult, Is.True); Assert.That(errorMessage, Is.Null); }); } // 测试非法输入的场景 [Test] [TestCaseSource(nameof(InvalidIncomeTestCases))] public (bool, string) IncomeCreate_InvalidInput_ReturnsError(Income income) { var bLL = new Family_Budget_BLL.IncomeBLL(); return bLL.Create(income); } } }
方式2:在测试方法内直接构造测试用例(适合简单场景)
如果测试用例不多,也可以直接在方法内构造所有场景并逐一验证:
namespace Test_Layer { [TestFixture] public class NunitTests { [Test] public void IncomeCreate_TestAllScenarios() { var bLL = new Family_Budget_BLL.IncomeBLL(); // 测试合法输入 var validIncomes = new List<Income> { new Income { Date = "01-01-2000", Amount = 1000, Payee_ID = 1, Payor = "Bob", Description = "Contract no 1" }, new Income { Date = "02-01-2000", Amount = 1500, Payee_ID = 2, Payor = "Jimmy", Description = "Contract no 2" } }; foreach (var income in validIncomes) { var (successResult, errorMessage) = bLL.Create(income); Assert.Multiple(() => { Assert.That(successResult, Is.True); Assert.That(errorMessage, Is.Null); }); } // 测试非法输入:Date为null var nullDateIncome = new Income { Date = null, Amount = 1000, Payee_ID = 1 }; var (nullDateSuccess, nullDateError) = bLL.Create(nullDateIncome); Assert.Multiple(() => { Assert.That(nullDateSuccess, Is.False); Assert.That(nullDateError, Is.EqualTo("Fill all the required fields!")); }); // 测试非法输入:Amount为0 var zeroAmountIncome = new Income { Date = "01-01-2000", Amount = 0, Payee_ID = 1 }; var (zeroAmountSuccess, zeroAmountError) = bLL.Create(zeroAmountIncome); Assert.Multiple(() => { Assert.That(zeroAmountSuccess, Is.False); Assert.That(zeroAmountError, Is.EqualTo("Fill all the required fields!")); }); // 测试非法输入:Payee_ID为0 var zeroPayeeIdIncome = new Income { Date = "01-01-2000", Amount = 1000, Payee_ID = 0 }; var (zeroPayeeIdSuccess, zeroPayeeIdError) = bLL.Create(zeroPayeeIdIncome); Assert.Multiple(() => { Assert.That(zeroPayeeIdSuccess, Is.False); Assert.That(zeroPayeeIdError, Is.EqualTo("Fill all the required fields!")); }); } } }
关键说明
- 参数化测试:通过
[TestCaseSource]可以批量传入自定义类对象,每个测试用例会单独执行,方便定位问题 - 场景覆盖:除了合法输入,必须测试必填项缺失的异常场景,保证业务逻辑的完整性
- Assert.Multiple:使用这个方法可以在一次断言失败后继续执行其他断言,一次性展示所有错误
- 依赖隔离:如果
incomeDAL.Create依赖数据库等外部资源,建议使用Moq等框架模拟DAL层,避免测试依赖外部环境
内容的提问来源于stack exchange,提问作者Amir
相关产品推荐
相关产品推荐

