.NET Core中使用NUnit测试服务Save方法测试失败问题求解
问题核心原因
- 被测对象使用错误:你需要测试的是自己实现的
ToDoService类的业务逻辑,但你在测试中全程使用Moq生成的模拟IToDoService对象,模拟对象不会执行你写的真实SaveTodo、GetAllTodos方法逻辑。 - 模拟方法未配置返回值:Moq生成的未显式配置的方法,返回引用类型时默认值为null,因此你调用
GetAllTodos会得到null,断言自然失败。
修复方案
场景1:测试你编写的ToDoService真实逻辑(推荐,符合单元测试被测对象要求)
这种场景下完全不需要MockIToDoService,直接实例化真实的ToDoService类即可。注意因为你用了静态列表存储数据,需要每次测试前后清空列表,避免多个测试之间数据互相干扰。
调整后的测试代码:
private IToDoService todoService; [SetUp] public void Setup() { // 直接实例化真实服务类,使用你实现的业务逻辑 todoService = new ToDoService(); // 可选:每次测试前清空静态列表,避免脏数据影响,你需要在ToDoService中新增对应静态方法 // ToDoService.ClearDatabase(); } [TearDown] public void TearDown() { // 测试结束后也清空静态列表 // ToDoService.ClearDatabase(); } [Test] public void TestSave() { todoService.SaveTodo("new item"); var data = todoService.GetAllTodos(); Assert.IsTrue(data.Any(a => a.Text == "new item")); }
配套ToDoService补充代码(可选,用于清理静态数据):
public class ToDoService : IToDoService { private static List<ToDoItem> database = new List<ToDoItem>(); // 新增清空静态列表的方法,用于测试前后清理数据 public static void ClearDatabase() { database.Clear(); } // 剩余原有代码保持不变 public List<ToDoItem> GetAllTodos() { return database; } public void SaveTodo(string text) { database.Add(new ToDoItem { Text = text }); } }
场景2:仅验证模拟对象的方法调用逻辑(用于测试依赖IToDoService的其他类时使用,当前场景不推荐)
如果你确实需要使用模拟对象,需要手动配置SaveTodo的回调逻辑和GetAllTodos的返回值:
private Mock<IToDoService> todoService; private List<ToDoItem> mockDatabase = new List<ToDoItem>(); [SetUp] public void Setup() { todoService = new Mock<IToDoService>(); // 配置GetAllTodos返回模拟的列表 todoService.Setup(x => x.GetAllTodos()).Returns(mockDatabase); // 配置SaveTodo被调用时,往模拟列表添加对应数据 todoService.Setup(x => x.SaveTodo(It.IsAny<string>())) .Callback<string>(text => mockDatabase.Add(new ToDoItem { Text = text })); } [Test] public void TestSave() { todoService.Object.SaveTodo("new item"); var data = todoService.Object.GetAllTodos(); Assert.IsTrue(data.Any(a => a.Text == "new item")); }
内容的提问来源于stack exchange,提问作者adeveloper
相关产品推荐
相关产品推荐

