You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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框架)

  1. 在测试项目中通过NuGet安装Moq包
  2. 编写测试用例:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 20:46:04