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

C# 如何在Moq中设置重载方法调用?,c#,moq,overloading,C#,Moq,Overloading,我试图模拟映射接口IMapper: public interface IMapper<TFoo, TBar> { TBar Map(TFoo foo); TFoo Map(TBar bar); } 但是,当进行第二次Map调用时,映射器模拟会抛出,因为它只需要一次调用 在运行时的设置过程中观察映射器模拟,我可以查看映射(TFoo foo)重载的注册情况,然后在设置映射(TBar bar)重载时看到它被替换 这是Moq处理设置的方式的问题,还是在这种情况下需要使用不同

我试图模拟映射接口
IMapper

public interface IMapper<TFoo, TBar> {
    TBar Map(TFoo foo);
    TFoo Map(TBar bar);
}
但是,当进行第二次
Map
调用时,映射器模拟会抛出,因为它只需要一次调用

在运行时的设置过程中观察映射器模拟,我可以查看
映射(TFoo foo)
重载的注册情况,然后在设置
映射(TBar bar)
重载时看到它被替换

这是Moq处理设置的方式的问题,还是在这种情况下需要使用不同的语法

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

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

    public TestClass() {
        //...
        _mapperMock = _repository.Create
            <IMapper<RequestData.Foo, ResponseData.Bar>>();
        //...
     }
}
公共类TestClass{
私有只读MockRepository _repository=新MockRepository(MockBehavior.Strict);
公共测试类(){
//...
_mapperMock=\u repository.Create
();
//...
}
}
编辑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());
}
公共接口IMapper{
TFoo图(TBar条);
TBar地图(TFoo-foo);
}
公开课Foo{
公共覆盖int GetHashCode(){
//返回base.GetHashCode();
返回1;
}
}
公共类酒吧{
公共覆盖int GetHashCode(){
//返回base.GetHashCode();
返回2;
}
}
[测试]
公开无效测试()
{
//安排
var\u mapperMock=新模拟(MockBehavior.Strict);
var fooMock=new Mock();
var barMock=new Mock();
_Setup(m=>m.Map(fooMock.Object)).Returns(barMock.Object);
_Setup(m=>m.Map(barMock.Object)).Returns(fooMock.Object);
//Act-在该评论下面的第一行中断
var bar=\u mapperMock.Object.Map(fooMock.Object);
var foo=_mapperMock.Object.Map(barMock.Object);
//断言
_Verify(x=>x.Map(fooMock.Object),Times.Once());
_Verify(x=>x.Map(barMock.Object),Times.Once());
}
如果我在
Foo
Bar
上注释掉
GetHashCode()
覆盖,或者在两者上注释掉
GetHashCode()
覆盖,则测试用例通过。或者,如果我没有使用
Foo
Bar
Mock
s,测试用例通过

编辑3
我用更详细的测试用例来解决这个问题。

不确定您的
Foo
Bar
类是什么样子的,但我通过了这个测试(Moq 4.0.10827.0,这是NuGet中最新的一个)

使用Moq;
使用NUnit.Framework;
命名空间控制台应用程序1
{
[测试夹具]
公开课考试
{
[测试]
公开无效测试()
{
//安排
var_mapperMock=new Mock();
var fooMock=new Mock();
var barMock=new Mock();
_Setup(m=>m.Map(fooMock.Object)).Returns(barMock.Object);
_Setup(m=>m.Map(barMock.Object)).Returns(fooMock.Object);
//表演
var bar=\u mapperMock.Object.Map(fooMock.Object);
var foo=_mapperMock.Object.Map(barMock.Object);
//断言
arame(bar,barMock.Object);
areseme(foo,fooMock.Object);
_Verify(x=>x.Map(fooMock.Object),Times.Once());
_Verify(x=>x.Map(barMock.Object),Times.Once());
}
}
公共类酒吧
{
}
公开课Foo
{
}
}

能否在实例化mapperMock的地方包含您的代码?谢谢。我唯一能看到你上面的代码失败的时候是如果泛型TFoo和TBar是相同的类型。例如,var_mapperMock=new Mock();如果它们是不同的(例如var _mapperMock=new Mock();),那么它们应该是不同的类型,继承自不同的子类型。当我在调试器中单步执行测试时,我可以看到方法分辨率正确变化,但是在进行第二次
Setup
调用时,第一次调用被第二次调用所取代。我还将添加实际的实例化代码。模拟的默认行为是
Loose
。如果
\u mapperMock
使用
Strict
行为,上述测试是否仍然通过?我使用
var\u mapperMock=new Mock(MockBehavior.Strict)测试了上述测试并且它仍然通过。有趣的是…我想知道它是否与使用
MockRepository
定义映射器有关。我将尝试直接实例化
\u mapperMock
,看看这是否有区别。在我的案例中,仍然使用来自网站的DLL(否则我们使用的是从源AFAICT构建的副本),并使用本地实例化的映射器模拟。但是,我发现它与
Foo
Bar
下面的基类有关-如果我在没有指定基类的情况下运行测试,它将通过,但是如果我指定
Foo
Bar
扩展各自的基类,测试失败。你是否发布了
Foo
Bar
的代码以及导致测试失败的基本类型?
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());
}
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
    {
    }
}