【问题标题】:Passing Moq mock-objects to constructor将MOQ模型对象传递给构造函数
【发布时间】:2011-10-24 02:30:25
【问题描述】:

我使用 RhinoMocks 已经有一段时间了,但刚刚开始研究起订量。我有这个非常基本的问题,令我惊讶的是,这并不是开箱即用的。假设我有以下类定义:

public class Foo
{
    private IBar _bar; 
    public Foo(IBar bar)
    {
        _bar = bar; 
    }
    ..
}

现在我有一个测试,我需要模拟发送给 Foo 的 IBar。在 RhinoMocks 中,我会像下面这样简单地做,它会很好用:

var mock = MockRepository.GenerateMock<IBar>(); 
var foo = new Foo(mock); 

但是,在最小起订量中,这似乎并不相同。我这样做如下:

var mock = new Mock<IBar>(); 
var foo = new Foo(mock); 

但是,现在它失败了 - 告诉我“无法从 'Moq.Mock' 转换为 'IBar'。我做错了什么?推荐使用 Moq 的方法是什么?

【问题讨论】:

    标签: c# .net mocking moq


    【解决方案1】:

    需要通过mock的对象实例

    var mock = new Mock<IBar>();  
    var foo = new Foo(mock.Object);
    

    您还可以使用模拟对象来访问实例的方法。

    mock.Object.GetFoo();
    

    moq docs

    【讨论】:

    • 但我只需要在调用foo.Object 时初始化mock.Object。我基本上在寻找的是能够传递给Foo 的构造函数,即原始Mock&lt;IBar&gt;,在我调用mock.Object 时被调用。有没有办法做到这一点?
    【解决方案2】:
    var mock = new Mock<IBar>().Object
    

    【讨论】:

    • +1 仅落后于接受答案的答案 10 秒。谢谢!
    • 我通常不会将对象实例分配给这样的变量,因为您可能希望为特定行为设置模拟。
    • 只是为了显示 .Object 这是他遇到的运行时错误的解决方案:-)
    【解决方案3】:

    前面的答案是正确的,但为了完整起见,我想再添加一种方法。使用 moq 库的 Linq 功能。

    public interface IBar
    {
        int Bar(string s);
    
        int AnotherBar(int a);
    }
    
    public interface IFoo
    {
        int Foo(string s);
    }
    
    public class FooClass : IFoo
    {
        private readonly IBar _bar;
    
        public FooClass(IBar bar)
        {
            _bar = bar;
        }
    
        public int Foo(string s) 
            => _bar.Bar(s);
    
        public int AnotherFoo(int a) 
            => _bar.AnotherBar(a);
    }
    

    您可以使用Mock.Of&lt;T&gt; 并避免使用.Object 来电。

    FooClass sut = new FooClass(Mock.Of<IBar>(m => m.Bar("Bar") == 2 && m.AnotherBar(1) == 3));
    int r = sut.Foo("Bar"); //r should be 2
    int r = sut.AnotherFoo(1); //r should be 3
    

    或使用匹配器

    FooClass sut = new FooClass(Mock.Of<IBar>(m => m.Bar(It.IsAny<string>()) == 2));
    int r = sut.Foo("Bar"); // r should be 2
    

    【讨论】:

    • 如何在模拟定义中指定几个方法/参数?类似new FooClass(Mock.Of&lt;IBar&gt;(m =&gt; m.Bar("Bar") == 2, k =&gt; k.Ready() == true ));
    • @ulkas 你应该使用&amp;&amp;,我已经更新了答案,FooClass(Mock.Of&lt;IBar&gt;(m =&gt; m.Bar("Bar") == 2 &amp;&amp; m.Ready() == true ));
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-04
    • 2019-03-28
    • 1970-01-01
    • 1970-01-01
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多