AutoFixture:mock方法不返回冻结的实例

时间:2013-02-05 13:47:25

标签: moq autofixture

我正在尝试编写这个简单的测试:

var fixture = new Fixture().Customize(new AutoMoqCustomization());

var postProcessingAction = fixture.Freeze<Mock<IPostProcessingAction>>();
var postProcessor = fixture.Freeze<PostProcessor>();

postProcessor.Process("", "");

postProcessingAction.Verify(action => action.Do());

Verify检查失败 postProcessor.Process的代码是

public void Process(string resultFilePath, string jobId)
{
    IPostProcessingAction postProcessingAction =
        postProcessingActionReader
            .CreatePostProcessingActionFromJobResultXml(resultFilePath);

    postProcessingAction.Do();
}

postProcessingActionReader是通过构造函数初始化的接口字段。

我希望测试能够通过但是失败了,事实证明IPostProessingAction方法返回的CreatePostProcessingActionFromJobResultXml实例与fixture.Freeze<>返回的实例不同。

我的期望是,在冻结这个Mock对象后,它会在所需的每个地方注入IPostProcessingAction接口的底层模拟,并使所有返回IPostProcessingAction的模拟方法返回同一个对象。 / p>

我对mock方法的返回值的期望是否不正确? 有没有办法改变这种行为,以便mock方法返回相同的冻结实例?

2 个答案:

答案 0 :(得分:5)

您需要Freeze IPostProcessingActionReader组件。

以下测试将通过:

[Fact]
public void Test()
{
    var fixture = new Fixture()
        .Customize(new AutoMoqCustomization());

    var postProcessingActionMock = new Mock<IPostProcessingAction>();

    var postProcessingActionReaderMock = fixture
        .Freeze<Mock<IPostProcessingActionReader>>();

    postProcessingActionReaderMock
        .Setup(x => x.CreatePostProcessingActionFromJobResultXml(
            It.IsAny<string>()))
        .Returns(postProcessingActionMock.Object);

    var postProcessor = fixture.CreateAnonymous<PostProcessor>();
    postProcessor.Process("", "");

    postProcessingActionMock.Verify(action => action.Do());
}

假设类型定义为:

public interface IPostProcessingAction
{
    void Do();
}

public class PostProcessor
{
    private readonly IPostProcessingActionReader actionReader;

    public PostProcessor(IPostProcessingActionReader actionReader)
    {
        if (actionReader == null)
            throw new ArgumentNullException("actionReader");

        this.actionReader = actionReader;
    }

    public void Process(string resultFilePath, string jobId)
    {
        IPostProcessingAction postProcessingAction = this.actionReader
            .CreatePostProcessingActionFromJobResultXml(resultFilePath);

        postProcessingAction.Do();
    }
}

public interface IPostProcessingActionReader
{
    IPostProcessingAction CreatePostProcessingActionFromJobResultXml(
        string resultFilePath);
}

如果您将自动混合declaratively与xUnit.net extension一起使用,则可以进一步简化测试:

[Theory, AutoMoqData]
public void Test(
    [Frozen]Mock<IPostProcessingActionReader> readerMock,
    Mock<IPostProcessingAction> postProcessingActionMock,
    PostProcessor postProcessor)
{
    readerMock
        .Setup(x => x.CreatePostProcessingActionFromJobResultXml(
            It.IsAny<string>()))
        .Returns(postProcessingActionMock.Object);

    postProcessor.Process("", "");

    postProcessingActionMock.Verify(action => action.Do());
}

AutoMoqDataAttribute定义为:

internal class AutoMoqDataAttribute : AutoDataAttribute
{
    internal AutoMoqDataAttribute()
        : base(new Fixture().Customize(new AutoMoqCustomization()))
    {
    }
}

答案 1 :(得分:4)

从3.20.0开始,您可以使用AutoConfiguredMoqCustomization。这将自动配置所有模拟,以便其成员&#39;返回值由AutoFixture生成。

换句话说,它会自动配置您的postProcessingActionReader以返回冻结的postProcessingAction

只需改变一下:

var fixture = new Fixture().Customize(new AutoMoqCustomization());

到此:

var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());