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

xUnit测试问题:如何模拟ClassA工厂以测试依赖该工厂的ClassB

解决方案

一、单元测试工厂Mock逻辑编写

你注入的Func<int, IClassA>本质是入参为int、返回值为IClassA的委托,有两种常用实现方式:

方式1:直接构造工厂委托(无Mock库也可使用,适合简单场景)

不需要引入Mock框架就能直接实现,代码如下:

[Fact]
public void TestClassBReturnsCorrectString()
{
    // Arrange
    // 直接构造符合要求的工厂委托
    Func<int, IClassA> mockClassAFact = (inputNumber) => 
    {
        // 逻辑简单的场景可以直接返回真实ClassA实例
        return new ClassA(inputNumber);
        
        // 如果IClassA有复杂外部依赖需要Mock,用Moq写法如下
        // var mockClassA = new Mock<IClassA>();
        // mockClassA.Setup(x => x.ReturnString()).Returns(inputNumber.ToString());
        // return mockClassA.Object;
    };
    IClassB classB = new ClassB(mockClassAFact);
 
    // Act
    string aString = classB.ExampleFct();

    // Assert
    Assert.Equal("5", aString); // 推荐用Equal代替True判断,报错信息更清晰
}

注:你提供的ClassB代码中IClassA classA = _classAFactory(_exampleValue)行末尾缺少分号,会导致编译报错,需要补充。

方式2:带调用验证的Moq实现

如果需要验证工厂的调用次数、传入参数是否符合预期,可以用Moq框架做更严谨的校验:

[Fact]
public void TestClassBReturnsCorrectString_WithVerify()
{
    // Arrange
    var mockClassA = new Mock<IClassA>();
    mockClassA.Setup(x => x.ReturnString()).Returns("5");
    
    // 模拟工厂,验证传入参数是5时返回模拟的IClassA实例
    var mockFactory = new Mock<Func<int, IClassA>>();
    mockFactory.Setup(f => f.Invoke(It.Is<int>(v => v == 5))).Returns(mockClassA.Object);

    IClassB classB = new ClassB(mockFactory.Object);
 
    // Act
    string aString = classB.ExampleFct();

    // Assert
    Assert.Equal("5", aString);
    // 额外验证调用逻辑是否符合预期
    mockFactory.Verify(f => f.Invoke(5), Times.Once);
    mockClassA.Verify(x => x.ReturnString(), Times.Once);
}

二、Autofac 场景专用解决方案

Autofac本身内置对委托工厂的支持,同时提供了测试专用的扩展包:

业务代码注册方案

正常业务代码中不需要手动注册Func<int, IClassA>工厂,Autofac会自动识别该类型依赖,你只需要注册基础服务即可:

// Autofac服务注册
builder.RegisterType<ClassA>().As<IClassA>();
builder.RegisterType<ClassB>().As<IClassB>();

完成上述注册后,Autofac会自动生成符合要求的工厂实例注入ClassB构造函数。

单元测试专用方案

测试场景可以使用官方的Autofac.Extras.Moq扩展包,自动处理所有依赖的Mock逻辑,无需手动构造工厂:

  1. 先安装NuGet包:Autofac.Extras.Moq
  2. 测试代码如下:
[Fact]
public void TestClassBWithAutofacMoq()
{
    using var mock = AutoMock.GetLoose();
    // 配置IClassA的模拟返回
    mock.Mock<IClassA>().Setup(x => x.ReturnString()).Returns("5");
    
    // Autofac自动生成Func<int, IClassA>工厂实现,直接创建ClassB实例即可
    var classB = mock.Create<ClassB>();
    
    // Act
    var result = classB.ExampleFct();
    
    // Assert
    Assert.Equal("5", result);
    // 同样支持调用逻辑验证
    mock.Mock<Func<int, IClassA>>().Verify(f => f.Invoke(5), Times.Once);
}

内容的提问来源于stack exchange,提问作者RadioMan85

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 00:36:01