可以冻结一个模拟的功能?

时间:2015-07-29 12:44:58

标签: unit-testing autofixture automoq

我想测试我的Func类型是否已实际执行。为此,我创建了一个Mock,但我遇到了来自Autofixture的Exception。我尝试FreezeFunc(没有Mock),这有效。有人可以解释发生了什么或指导我采取正确的方式吗?

异常消息:

  

类型' Ploeh.AutoFixture.Kernel.IllegalRequestException'的例外情况发生在Ploeh.AutoFixture.dll但未在用户代码中处理   附加信息:检测到IntPtr请求。这是一个不安全的资源,如果使用该进程将导致进程崩溃,因此请求被拒绝。 IntPtr请求的常见来源是对代理(如Func或Action)的请求。如果是这种情况,预期的解决方法是通过指定正确的创建策略来自定义(注册或注入)违规类型。

代码:

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 

2 个答案:

答案 0 :(得分:4)

此行为归因于AutoConfiguredMoqCustomization

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

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

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

这是你应该做的:

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

答案 1 :(得分:2)

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
}