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

如何在FakeItEasy中为泛型接口的out参数设置模拟值?

使用FakeItEasy模拟带out参数的泛型接口方法

问题场景

需要在xUnit测试中用FakeItEasy模拟泛型接口IFakeTest<T>的GetData方法(包含out参数),原代码及遇到的错误如下:

原测试代码

#region FakeItEasyDebugging
public interface IFakeTest<T> : IDisposable where T : new()
{
    bool GetData(string key, out T data);
}

public class TestClass
{
    public int Foo { get; set; } = 0;
}

public class FakeTest
{
    [Fact]
    public void TestFakeItEasy()
    {
        const string testKey = "some";

        IFakeTest<TestClass> testObj = A.Fake<IFakeTest<TestClass>>();
        A.CallTo(() => testObj.GetData(testKey, out data)).Returns(true).AssignsOutAndRefParameters(new TestClass());
    }
}
#endregion

遇到的错误

  • 直接使用out data:报错CS0103,提示data在当前上下文中不存在
  • 尝试out TestClass data:报错CS8198,lambda表达式中不能声明变量
  • 尝试out TestClass:报错CS0118,TestClass是类型,此处需要变量

正确实现方式

FakeItEasy处理out参数时,需要满足C#语法要求的同时指定模拟行为,以下两种写法都可行:

方式1:提前声明变量作为占位符

[Fact]
public void TestFakeItEasy()
{
    const string testKey = "some";
    IFakeTest<TestClass> testObj = A.Fake<IFakeTest<TestClass>>();
    
    // 提前声明out参数对应的变量,初始值不影响模拟逻辑
    TestClass data;
    A.CallTo(() => testObj.GetData(testKey, out data))
      .Returns(true)
      .AssignsOutAndRefParameters(new TestClass());

    // 验证模拟效果
    var result = testObj.GetData(testKey, out var outputData);
    Assert.True(result);
    Assert.NotNull(outputData);
    Assert.Equal(0, outputData.Foo);
}

方式2:使用A<T>.Ignored简化占位符

如果不需要在配置阶段使用该变量,可直接用FakeItEasy提供的A<T>.Ignored作为out参数的占位符:

[Fact]
public void TestFakeItEasy()
{
    const string testKey = "some";
    IFakeTest<TestClass> testObj = A.Fake<IFakeTest<TestClass>>();
    
    A.CallTo(() => testObj.GetData(testKey, out A<TestClass>.Ignored))
      .Returns(true)
      .AssignsOutAndRefParameters(new TestClass());

    // 验证模拟效果
    var result = testObj.GetData(testKey, out var outputData);
    Assert.True(result);
    Assert.NotNull(outputData);
}

原理说明

AssignsOutAndRefParameters方法会在模拟方法被调用时,将指定的值赋值给out/ref参数;提前声明的变量或A<T>.Ignored仅用于满足C#语法编译要求,FakeItEasy实际会用传入的目标值覆盖out参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:17:32