MOQ.Setup如何在这种情况下工作 - 多次调用时?

时间:2014-09-01 08:48:06

标签: unit-testing moq

我正在寻找一个关于moq's Setup方法在设置一个模拟对象时的确切解释,该模拟对象将从“被测系统”中多次调用(sut)

例如:

如果我有一个模拟对象设置并调用我的Sut方法。

var inputParamObject = new inputParamObject();

this.mock.Setup(x => x.MethodCall(inputParam).Returns(this.mock.Object);

Sut.WithCallLoopingMethodThatCallsTheMockObject();

现在,我正在处理的真正代码是遗留的,而且很难在这里显示,所以不幸的是,这是我认为正在发生的事情的简单表示。

问题,我看到的是如果inputParamObject用于循环的第一次迭代,它会重新启动正确的模拟对象。但是,在第二次迭代中,它返回null。

如果我将上面的代码更改为使用第二个InputParamObject,它将再次返回模拟并且我的测试将通过:

var inputParam = new InputParam();
var inputParam2 = new InputParam();

this.mock.Setup(x => x.MethodCall(inputParam).Returns(this.mock.Object);
this.mock.Setup(x => x.MethodCall(inputParam2).Returns(this.mock.Object);

Sut.WithCallLoopingMethodThatCallsTheMockObject();

我认为模拟的第二个设置只会覆盖第一个,但似乎并非如此。我也知道我可以这样设置,测试将通过。

this.mock.Setup(x => x.MethodCall(It.IsAny<InputParamObject>).Returns(this.mock.Object);

我很抱歉这是一个人为的例子,也许需要更多的细节来理解,但

当我有一个安装调用时,有人能告诉我究竟发生了什么,而在这个例子中有两个吗?

此指针的特定参考资料的指针也很棒。

由于

1 个答案:

答案 0 :(得分:0)

我从未遇到过多次调用模拟对象的方法的任何问题。我认为您的测试失败可能还有其他几个原因。

  1. 您似乎每个测试夹具都有一个模拟对象实例。其他测试可能会对模拟对象设置产生副作用。尝试在每个测试中创建自己的实例。您可能会发现有用的单元测试上下文模式 http://java.dzone.com/articles/introducing-unit-testing

  2. 您的方法WithCallLoopingMethodThatCallsTheMockObject可能会将inputParamObject的不同实例发送到MethodCall。也许你必须覆盖inputParamObject的Equals方法。

  3. 我成功运行的代码如下。

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            const int SERVICE_ID = 123;
            ParamObject callParam = new ParamObject(42);
            var fakeService = new Mock<IService>();
    
            fakeService.Setup(call => call.MethodCall(callParam)).Returns(fakeService.Object);
            fakeService.Setup(call => call.Id).Returns(SERVICE_ID);
            Processor sut = new Processor(fakeService.Object, callParam);
    
            // --- Act
            sut.WithCallLoopingMethodThatCallsTheMockObject();
        }
    }
    
    public interface IService
    {
        int Id { get; }
        IService MethodCall(ParamObject param);
    }
    
    public class ParamObject
    {
        private int _id = 0;
    
        public ParamObject(int id)
        {
            _id = id;
        }
    }
    
    public class Processor
    {
        private IService _service;
        private ParamObject _serviceCallParam;
    
        public Processor(IService service, ParamObject serviceCallParam)
        {
            _service = service;
            _serviceCallParam = serviceCallParam;
        }
    
        public void WithCallLoopingMethodThatCallsTheMockObject()
        {
            for(int i=0; i<20; i++)
            {
                IService srv = _service.MethodCall(_serviceCallParam);
                Console.WriteLine(String.Format("Iteration {0:00}, service instance id={1}", i, srv.Id));
            }
        }
    }