如何在Moq中设置重载的方法调用?

aro*_*eer 5 c# overloading moq

我正在尝试模拟映射接口IMapper

public interface IMapper<TFoo, TBar> {
    TBar Map(TFoo foo);
    TFoo Map(TBar bar);
}
Run Code Online (Sandbox Code Playgroud)

在我的测试中,我将模拟映射器设置为期望每个都被调用(围绕NHibernate update操作):

//...
_mapperMock.Setup(m => m.Map(fooMock.Object)).Returns(barMock.Object);
_mapperMock.Setup(m => m.Map(barMock.Object)).Returns(fooMock.Object);
//...
Run Code Online (Sandbox Code Playgroud)

但是,在进行第二次Map调用时,映射器模拟程序将抛出异​​常,因为它只希望进行一次调用。

看着在运行时安装过程中的mapper模拟,我可以看到Map(TFoo foo)注册了过载,然后在设置Map(TBar bar)过载时看到了它的替换。

Moq处理设置的方式是否有问题,或者在这种情况下需要使用其他语法吗?

编辑 这是来自测试构造函数的实际实例化代码:

public class TestClass {
    private readonly MockRepository _repository = new MockRepository(MockBehavior.Strict);

    public TestClass() {
        //...
        _mapperMock = _repository.Create
            <IMapper<RequestData.Foo, ResponseData.Bar>>();
        //...
     }
}
Run Code Online (Sandbox Code Playgroud)

编辑2

这是一个完整的失败测试用例:

public interface IMapper<TFoo, TBar> {
    TFoo Map(TBar bar);
    TBar Map(TFoo foo);
}

public class Foo {
    public override int GetHashCode() {
        // return base.GetHashCode();
        return 1;
    }
}

public class Bar {
    public override int GetHashCode() {
        // return base.GetHashCode();
        return 2;
    }
}

[Test]
public void TestIt()
{
    // Arrange
    var _mapperMock = new Mock<IMapper<Foo, Bar>>(MockBehavior.Strict);
    var fooMock = new Mock<Foo>();
    var barMock = new Mock<Bar>();

    _mapperMock.Setup(m => m.Map(fooMock.Object)).Returns(barMock.Object);
    _mapperMock.Setup(m => m.Map(barMock.Object)).Returns(fooMock.Object);

    // Act - breaks on first line below this comment
    var bar = _mapperMock.Object.Map(fooMock.Object);
    var foo = _mapperMock.Object.Map(barMock.Object);

    // Assert
    _mapperMock.Verify(x => x.Map(fooMock.Object), Times.Once());
    _mapperMock.Verify(x => x.Map(barMock.Object), Times.Once());
}
Run Code Online (Sandbox Code Playgroud)

如果我GetHashCode()FooBar或两者上都注释掉了替代,则测试用例通过。或者,如果我不使用MockFooBar,测试用例通过。

编辑3 我针对这个问题打开了Moq问题347,其中包含更详细的测试用例。

Cod*_*ike 2

不确定你的FooBar类是什么样子,但这个测试对我来说通过了(Moq 4.0.10827.0,这是 NuGet 中最新的)

using Moq;
using NUnit.Framework;

namespace ConsoleApplication1
{
    [TestFixture]
    public class Tests
    {
        [Test]
        public void TestIt()
        {
            // Arrange
            var _mapperMock = new Mock<IMapper<Foo, Bar>>();
            var fooMock = new Mock<Foo>();
            var barMock = new Mock<Bar>();

            _mapperMock.Setup(m => m.Map(fooMock.Object)).Returns(barMock.Object);
            _mapperMock.Setup(m => m.Map(barMock.Object)).Returns(fooMock.Object);

            // Act
            var bar = _mapperMock.Object.Map(fooMock.Object);
            var foo = _mapperMock.Object.Map(barMock.Object);

            // Assert
            Assert.AreSame(bar, barMock.Object);
            Assert.AreSame(foo, fooMock.Object);

            _mapperMock.Verify(x => x.Map(fooMock.Object), Times.Once());
            _mapperMock.Verify(x => x.Map(barMock.Object), Times.Once());
        }
    }

    public class Bar
    {
    }

    public class Foo
    {
    }
}
Run Code Online (Sandbox Code Playgroud)