如何在C# xUnit中Mock依赖注入服务并传入测试对象?
在依赖注入项目中Mock服务并传递给测试对象的方案
先指出原代码里的几个语法问题,避免测试时踩坑:
ClassToTest类定义里的public Class应为public class(C#语法错误)MethodToTest里的CustomService.Get()应改为_customService.Get()(需引用私有属性而非类名)Program.cs里的new (CustomService("Param"))应为new CustomService("Param")(构造函数调用语法错误)CustomService的Get()方法末尾缺少分号
以下分两种常见场景实现测试:
一、推荐:改用构造函数注入(更易测试)
Blazor的[Inject]属性适合框架自动注入,但测试环境下构造函数注入更直接,无需依赖框架注入逻辑。先修改ClassToTest:
public class ClassToTest { private readonly CustomService _customService; // 通过构造函数注入依赖 public ClassToTest(string args, CustomService customService) { _customService = customService; // ...其他初始化逻辑 } public void MethodToTest() { var result = _customService.Get(); } }
编写测试代码(使用Moq框架)
- 在测试项目中通过NuGet安装
Moq包 - 编写测试用例:
using Moq; using Xunit; // 也可替换为NUnit等测试框架 public class ClassToTestTests { [Fact] public void MethodToTest_ShouldCallCustomServiceGet() { // 1. Mock CustomService var mockCustomService = new Mock<CustomService>(); // 设置Mock的Get方法返回自定义值 mockCustomService.Setup(s => s.Get()).Returns("Mocked Hello"); // 2. 创建测试对象,传入Mock实例 var testObject = new ClassToTest("test args", mockCustomService.Object); // 3. 执行要测试的方法 testObject.MethodToTest(); // 4. 验证CustomService的Get方法是否被调用一次 mockCustomService.Verify(s => s.Get(), Times.Once); } }
二、保留属性注入的测试方式
如果必须保留[Inject]属性写法,测试时可手动给属性赋值(Blazor框架不会在测试环境自动注入):
修改ClassToTest(让属性可测试)
将protected属性改为internal,并在项目中添加InternalsVisibleTo特性,允许测试项目访问内部成员:
// 在ClassToTest所在项目的AssemblyInfo.cs中添加 [assembly: InternalsVisibleTo("你的测试项目名称")] public class ClassToTest { [Inject] internal CustomService _customService { get; set; } // 改为internal public ClassToTest(string args) { // ... } public void MethodToTest() { var result = _customService.Get(); } }
编写测试代码
using Moq; using Xunit; public class ClassToTestTests { [Fact] public void MethodToTest_ShouldUseMockedService() { // 1. Mock服务 var mockService = new Mock<CustomService>(); mockService.Setup(s => s.Get()).Returns("Mocked Result"); // 2. 创建测试对象并手动注入Mock实例 var testObject = new ClassToTest("test args"); testObject._customService = mockService.Object; // 3. 执行方法 testObject.MethodToTest(); // 4. 验证Get方法被调用一次 mockService.Verify(s => s.Get(), Times.Once); } }
补充优化建议
如果CustomService定义为接口(如ICustomService),Mock会更灵活,还能解耦依赖:
public interface ICustomService { string Get(); } public class CustomService : ICustomService { public string Get() => "Hello World"; }
注册服务时改为builder.Services.AddSingleton<ICustomService>(new CustomService("Param"));,测试时直接MockICustomService即可。
内容的提问来源于stack exchange,提问作者TheBlackOne
相关产品推荐
相关产品推荐

