【问题标题】:How is MOQ.Setup working in this scenario - when called multiple times?MOQ.Setup 在这种情况下如何工作 - 多次调用时?
【发布时间】:2014-09-01 08:48:05
【问题描述】:

我正在寻找在设置将从“被测系统”(sut) 中多次调用的模拟对象时moq's Setup 方法的确切工作原理的解释

例如:

如果我有一个模拟对象设置并调用我的 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);

抱歉,这是人为的示例,可能需要更多细节才能理解,但是,

谁能告诉我当我有一个设置调用而不是这个例子中的两个时发生了什么?

对于这种情况,还有一个指向特定参考资料的指针会很棒。

谢谢

【问题讨论】:

    标签: unit-testing moq


    【解决方案1】:

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

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

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

    我成功运行的代码如下。

    [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));
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      • 2021-12-06
      • 2018-06-16
      • 2017-06-21
      • 2018-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多