如何在“返回”中设置在 Moq 中模拟的输出参数的值?

J4N*_*J4N 3 .net c# unit-testing moq mocking

我在配置 Moq 时遇到了一些麻烦。

我有一个带有 out 参数的方法的模型。这个 out 参数真的被使用了,我需要根据我收到的参数用一些有意义的值填充它。

目前,我一直无法做到这一点,这可能吗?如何?

这是我目前的状态:

Mock<IMyMock> _mock = new Mock<IMyMock>();
bool someFlag= false;
_mock.Setup(m=>m.GetSomething(It.IsAny<DateTime>(), It.IsAny<DateTime>(), out someFlag))
     .Returns((DateTime start, DateTime end, bool someFlagInternal)=>{
        IEnumerable<SomeOtherClass> otherClasses = GenerateMockedData(start, end);
        //Assign something to someFlag, depending on start and end
        someFlag=true;//This has no effects
     }) ;
new SomeController(_mock.Object);
Run Code Online (Sandbox Code Playgroud)

在我的SomeController, 在特定方法上,我的真实非模拟代码调用它:

public class SomeController{}
    private IMyMock _someObjectThatWeDontKnowIsAMock;
    public SomeController(IMyMock someObjectThatWeDontKnowIsAMock) {
        _someObjectThatWeDontKnowIsAMock= someObjectThatWeDontKnowIsAMock;
    }

    private void ComputeNext() {
        Tuple<DateTime, DateTime> times = ComputeNextTimes();
        bool hasOverlap;
        IEnumerable<SomeOtherClass> otherClassesInstances = _someObjectThatWeDontKnowIsAMock.GenerateMockedData(times.Data1, times.Data2, out hasOverlap);
        if(hasOverlap) {
            //...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

每次我调用我的模拟时,它似乎都会返回 的第一个值someFlag,即使它是我修改的静态字段。

Nko*_*osi 5

您遇到的问题是因为设置中 out 参数的实例与执行测试时实际使用的实例不同。

取自Moq Quickstart文档

带有ref/out参数的方法的回调是可能的,但需要一些工作(以及 Moq 4.8 或更高版本)

创建一个委托来处理模拟调用。

 delegate IEnumerable<SomeOtherClass> GetSomethingCallback(DateTime start, DateTime end, out bool someFlag);
Run Code Online (Sandbox Code Playgroud)

在设置使用It.Ref<Bar>.IsAnyout参数,并使用该委托的Returns表达。

mock
    .Setup(_ => _.GetSomething(It.IsAny<DateTime>(), It.IsAny<DateTime>(), out It.Ref<bool>.IsAny))
    .Returns(new GetSomethingCallback((DateTime start, DateTime end, out bool someFlag) => {
        IEnumerable<SomeOtherClass> otherClasses = GenerateMockedData(start, end);
        //Assign something to someFlag, depending on start and end
        someFlag = true;
        return otherClasses;
    }));
Run Code Online (Sandbox Code Playgroud)

It.Ref<bool>.IsAny指示返回给委托与该通入嘲笑构件的实际对象的实例参考交互。