可以冻结函数的模拟吗?

Possible to Freeze a Mock of a func?

我想测试我的 Func 类型是否被实际执行。为此,我创建了一个 Mock,但我从 Autofixture 将 运行 转换为 Exception。我尝试 Freeze 只是 Func(没有 Mock),这有效。有人可以解释发生了什么或指导我以正确的方式做到这一点吗?

异常消息:

An exception of type 'Ploeh.AutoFixture.Kernel.IllegalRequestException' occurred in Ploeh.AutoFixture.dll but was not handled in user code Additional information: A request for an IntPtr was detected. This is an unsafe resource that will crash the process if used, so the request is denied. A common source of IntPtr requests are requests for delegates such as Func or Action. If this is the case, the expected workaround is to Customize (Register or Inject) the offending type by specifying a proper creational strategy.

代码:

public class DomainClassDummy
{
    public int Id { get; set; }
}

var frozenFunc = F.Freeze<Func<int, DomainClassDummy>>(); //works
var frozenMockOfFunc = F.Freeze<Mock<Func<int,DomainClassDummy>>>(); //fails 

此行为是由于 AutoConfiguredMoqCustomization

当使用 AutoConfiguredMoqCustomization 自定义 AutoFixture 时,它​​会将 Mock 实例的创建传递给特殊的构建器。 但是,此构建器获取内部类型 Func<int,DomainClassDummy> 并从中创建一个模拟,传递其构造函数的两个参数:objectIntPtr,这就是问题所在。

委托的默认构建器,使用 Linq Lambda 表达式创建其实例。

要使其正常工作,您必须自己创建模拟并将其注入 AutoFixture。注入它和冻结一样,除了你自己指定实例,而不是告诉 AutoFixture 为你创建一个。

这是你应该做的:

var mockOfFunc = new Mock<Func<int, DomainClassDummy>>();
F.Inject(mockOfFunc);

Marcio Rinaldi 给出的解释在技术上是正确的,但我发现解决方案并不令人满意,所以我将此功能添加到 AutoFixture.AutoMoq 3.31.1

此测试现在通过:

[Fact]
public void FixtureCanFreezeUsableMockOfFunc()
{
    // Fixture setup
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    var expected = fixture.Create<Uri>();
    var mockOfFunc = fixture.Freeze<Mock<Func<Guid, decimal, Uri>>>();
    mockOfFunc
        .Setup(f => f(It.IsAny<Guid>(), 1337m))
        .Returns(expected);

    // Exercise system
    var actual = mockOfFunc.Object(Guid.NewGuid(), 1337m);

    // Verify outcome
    Assert.Equal(expected, actual);
    // Teardown
}